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.

495 lines
18KB

  1. import 'package:farm_tpf/custom_model/CropPlot.dart';
  2. import 'package:farm_tpf/data/repository/repository.dart';
  3. import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart';
  4. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  5. import 'package:farm_tpf/presentation/screens/actions/crop_status/sc_edit_action_crop_status.dart';
  6. import 'package:farm_tpf/presentation/screens/actions/disease/sc_edit_action_disease.dart';
  7. import 'package:farm_tpf/presentation/screens/actions/dung/sc_edit_action_dung.dart';
  8. import 'package:farm_tpf/presentation/screens/actions/end/sc_edit_action_end.dart';
  9. import 'package:farm_tpf/presentation/screens/actions/environment_update/sc_edit_action_environment_update.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/harvest/sc_edit_action_harvest.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/harvest_process/sc_edit_action_harvest_process.dart';
  12. import 'package:farm_tpf/presentation/screens/actions/nursery/sc_edit_action_nursery.dart';
  13. import 'package:farm_tpf/presentation/screens/actions/other/sc_edit_action_other.dart';
  14. import 'package:farm_tpf/presentation/screens/actions/packing/sc_edit_action_packing.dart';
  15. import 'package:farm_tpf/presentation/screens/actions/plant/sc_edit_action_plant.dart';
  16. import 'package:farm_tpf/presentation/screens/actions/sell/sc_edit_action_sell.dart';
  17. import 'package:farm_tpf/presentation/screens/actions/spraying/sc_edit_action_spraying.dart';
  18. import 'package:farm_tpf/presentation/screens/actions/use_water/sc_edit_action_user_water.dart';
  19. import 'package:farm_tpf/presentation/screens/plot/sc_plot.dart';
  20. import 'package:farm_tpf/presentation/screens/plot_detail/bloc/plot_detail_bloc.dart';
  21. import 'package:farm_tpf/utils/const_color.dart';
  22. import 'package:farm_tpf/utils/const_string.dart';
  23. import 'package:flutter/material.dart';
  24. import 'package:flutter_bloc/flutter_bloc.dart';
  25. import 'package:farm_tpf/utils/formatter.dart';
  26. import 'package:get/get.dart';
  27. class PlotActionScreen extends StatefulWidget {
  28. int cropId;
  29. String cropCode;
  30. int cropType;
  31. PlotActionScreen({this.cropId, this.cropCode, this.cropType});
  32. @override
  33. _PlotActionScreenState createState() => _PlotActionScreenState();
  34. }
  35. class _PlotActionScreenState extends State<PlotActionScreen>
  36. with AutomaticKeepAliveClientMixin {
  37. List<ActionType> actions = new List<ActionType>();
  38. ScrollController _scrollController;
  39. var blocPlotDetail = PlotDetailBloc(repository: Repository());
  40. @override
  41. void initState() {
  42. super.initState();
  43. _scrollController = ScrollController()..addListener(() => setState(() {}));
  44. _initActionButtons();
  45. }
  46. @override
  47. void dispose() {
  48. blocPlotDetail.close();
  49. super.dispose();
  50. }
  51. _initActionButtons() {
  52. //type: 0- Trồng, 1- ướm
  53. if (widget.cropType == 1) {
  54. actions.add(ActionType(
  55. plot_action_nursery,
  56. EditActionNurseryScreen(
  57. cropId: widget.cropId,
  58. )));
  59. } else if (widget.cropType == 0) {
  60. actions.add(ActionType(
  61. plot_action_plant,
  62. EditActionPlantScreen(
  63. cropId: widget.cropId,
  64. )));
  65. }
  66. actions.add(ActionType(
  67. plot_action_crop_status,
  68. EditActionCropStatusScreen(
  69. cropId: widget.cropId,
  70. )));
  71. actions.add(ActionType(
  72. plot_action_environment_update,
  73. EditActionEnvironmentUpdate(
  74. cropId: widget.cropId,
  75. )));
  76. actions.add(ActionType(
  77. plot_action_dung,
  78. EditActionDungScreen(
  79. cropId: widget.cropId,
  80. )));
  81. actions.add(ActionType(
  82. plot_action_spraying,
  83. EditActionSprayingScreen(
  84. cropId: widget.cropId,
  85. )));
  86. actions.add(ActionType(
  87. plot_action_disease,
  88. EditActionDiseaseScreen(
  89. cropId: widget.cropId,
  90. )));
  91. actions.add(ActionType(
  92. plot_action_use_water,
  93. EditActionUseWaterScreen(
  94. cropId: widget.cropId,
  95. )));
  96. actions.add(ActionType(
  97. plot_action_other,
  98. EditActionOtherScreen(
  99. cropId: widget.cropId,
  100. )));
  101. actions.add(ActionType(
  102. plot_action_harvest,
  103. EditActionHarvestScreen(
  104. cropId: widget.cropId,
  105. )));
  106. actions.add(ActionType(
  107. plot_action_finish,
  108. EditActionEndScreen(
  109. cropId: widget.cropId,
  110. )));
  111. }
  112. Widget _createActionButtons(ActionType actionType, BuildContext _context) {
  113. return BlocBuilder<PlotDetailBloc, PlotDetailState>(
  114. cubit: blocPlotDetail,
  115. builder: (context, state) {
  116. return GestureDetector(
  117. onTap: () {
  118. Navigator.of(context)
  119. .push(MaterialPageRoute(
  120. builder: (context) => actionType.listScreen))
  121. .then((value) {
  122. if (value != null) {
  123. try {
  124. blocPlotDetail.add(OnRefresh(cropId: widget.cropId));
  125. } catch (e) {
  126. print(e);
  127. }
  128. }
  129. });
  130. },
  131. child: Container(
  132. margin: EdgeInsets.all(2.5),
  133. decoration: BoxDecoration(
  134. color: AppColors.WHITE,
  135. borderRadius: BorderRadius.all(Radius.circular(4.0)),
  136. boxShadow: <BoxShadow>[
  137. BoxShadow(
  138. color: AppColors.GRAY1.withOpacity(0.2),
  139. offset: Offset(1.1, 1.1),
  140. blurRadius: 4.0),
  141. ],
  142. ),
  143. child: Align(
  144. alignment: Alignment.center,
  145. child: Text(
  146. actionType.actionName,
  147. textAlign: TextAlign.center,
  148. style: TextStyle(
  149. fontWeight: FontWeight.w400,
  150. fontSize: 11,
  151. color: AppColors.BLACK2,
  152. ),
  153. )),
  154. ));
  155. });
  156. }
  157. bool _showTitle(BuildContext context) {
  158. var kExpandedHeight = MediaQuery.of(context).size.width * 0.625 + 24;
  159. return _scrollController.hasClients &&
  160. _scrollController.offset > kExpandedHeight - kToolbarHeight;
  161. }
  162. @override
  163. Widget build(BuildContext context) {
  164. return BlocBuilder<PlotDetailBloc, PlotDetailState>(
  165. cubit: blocPlotDetail,
  166. builder: (context, state) {
  167. return NestedScrollView(
  168. controller: _scrollController,
  169. headerSliverBuilder: (context, innerBoxScrolled) => [
  170. SliverAppBar(
  171. floating: false,
  172. pinned: false,
  173. backgroundColor: Colors.white,
  174. leading: Container(),
  175. title: null,
  176. // title: _showTitle(context) ? Text(plot_detail_title) : null,
  177. //Height flexibleSpace : WidthScreen /2 * 4/16 * 5(row) + 8(space) *3
  178. expandedHeight:
  179. MediaQuery.of(context).size.width * 0.625 + 24,
  180. flexibleSpace: _showTitle(context)
  181. ? null
  182. : BlocBuilder<PlotDetailBloc, PlotDetailState>(
  183. cubit: blocPlotDetail,
  184. builder: (contextB, state) {
  185. return FlexibleSpaceBar(
  186. centerTitle: true,
  187. title: GridView.count(
  188. shrinkWrap: true,
  189. crossAxisCount: 2,
  190. childAspectRatio: 16 / 4,
  191. children: actions.map(
  192. (item) {
  193. return _createActionButtons(
  194. item, contextB);
  195. },
  196. ).toList()),
  197. );
  198. })),
  199. ],
  200. body: BlocBuilder<PlotDetailBloc, PlotDetailState>(
  201. cubit: blocPlotDetail,
  202. builder: (context, state) {
  203. return InfinityView(
  204. cropId: widget.cropId,
  205. parentScroll: _scrollController,
  206. plotDetailBloc: blocPlotDetail,
  207. );
  208. }),
  209. );
  210. });
  211. }
  212. @override
  213. bool get wantKeepAlive => true;
  214. }
  215. class InfinityView extends StatefulWidget {
  216. int cropId;
  217. String cropCode;
  218. ScrollController parentScroll;
  219. PlotDetailBloc plotDetailBloc;
  220. InfinityView(
  221. {this.cropId,
  222. this.cropCode,
  223. @required this.parentScroll,
  224. @required this.plotDetailBloc});
  225. @override
  226. _InfinityViewState createState() => _InfinityViewState();
  227. }
  228. class _InfinityViewState extends State<InfinityView> {
  229. final _scrollController = ScrollController();
  230. final _scrollThreshold = 250.0;
  231. var heightOfActionButton = Get.width * 0.625 + 24;
  232. var heightHeaderList = 44;
  233. var heightListWithoutHeader = Get.height - (Get.width * 0.625 + 24) - 44;
  234. var currentOffset = 0.0;
  235. @override
  236. void initState() {
  237. widget.plotDetailBloc
  238. .add(DataFetched(cropId: widget.cropId, cropCode: widget.cropCode));
  239. _scrollController.addListener(() {
  240. final maxScroll = _scrollController.position.maxScrollExtent;
  241. final currentScroll = _scrollController.position.pixels;
  242. if (maxScroll - currentScroll < _scrollThreshold) {
  243. widget.plotDetailBloc
  244. .add(DataFetched(cropId: widget.cropId, cropCode: widget.cropCode));
  245. }
  246. });
  247. widget.parentScroll.addListener(() {
  248. setState(() {
  249. currentOffset = widget.parentScroll.offset;
  250. heightListWithoutHeader = Get.height -
  251. heightOfActionButton -
  252. heightHeaderList +
  253. currentOffset;
  254. });
  255. });
  256. super.initState();
  257. }
  258. @override
  259. Widget build(BuildContext context) {
  260. return BlocBuilder<PlotDetailBloc, PlotDetailState>(
  261. cubit: widget.plotDetailBloc,
  262. builder: (context, state) {
  263. if (state is PlotDetailFailure) {
  264. return Center(child: Text(state.errorString));
  265. }
  266. if (state is PlotDetailSuccess) {
  267. if (state.items.isEmpty) {
  268. return Center(child: Text("Không có dữ liệu lịch sử canh tác"));
  269. }
  270. List<Activities> currentItems = List<Activities>.from(state.items);
  271. return Scaffold(
  272. body: RefreshIndicator(
  273. child: Column(
  274. children: [
  275. Expanded(
  276. flex: 1,
  277. child: Container(
  278. alignment: Alignment.center,
  279. decoration: BoxDecoration(
  280. color: AppColors.WHITE_50,
  281. border: Border(
  282. top: BorderSide(
  283. width: 0.5, color: AppColors.DEFAULT),
  284. bottom: BorderSide(
  285. width: 0.5, color: AppColors.DEFAULT)),
  286. ),
  287. child: Container(
  288. child: Row(
  289. children: [
  290. Expanded(
  291. child: Text(
  292. plot_detail_title,
  293. textAlign: TextAlign.center,
  294. style: TextStyle(
  295. fontSize: 20,
  296. fontWeight: FontWeight.normal),
  297. )),
  298. GestureDetector(
  299. child: (0 == currentOffset)
  300. ? Icon(Icons.arrow_upward)
  301. : Icon(Icons.arrow_downward_outlined),
  302. onTap: () {
  303. if (currentOffset == 0) {
  304. widget.parentScroll.animateTo(
  305. heightOfActionButton,
  306. duration: Duration(milliseconds: 500),
  307. curve: Curves.easeOut);
  308. } else {
  309. widget.parentScroll.animateTo(0.0,
  310. duration: Duration(milliseconds: 500),
  311. curve: Curves.easeOut);
  312. }
  313. }),
  314. ],
  315. ),
  316. ),
  317. ),
  318. ),
  319. Expanded(
  320. flex: heightListWithoutHeader ~/ heightHeaderList,
  321. child: ListView.builder(
  322. physics: AlwaysScrollableScrollPhysics(),
  323. itemBuilder: (BuildContext context, int index) {
  324. return index >= state.items.length
  325. ? BottomLoader()
  326. : ItemInfinityWidget(
  327. currentItems: currentItems,
  328. item: state.items[index],
  329. currentPage: state.page,
  330. currentReachedMax: state.hasReachedMax);
  331. },
  332. itemCount: state.hasReachedMax
  333. ? state.items.length
  334. : state.items.length + 1,
  335. controller: _scrollController,
  336. ))
  337. ],
  338. ),
  339. onRefresh: () async {
  340. widget.plotDetailBloc.add(OnRefresh(
  341. cropId: widget.cropId, cropCode: widget.cropCode));
  342. }),
  343. );
  344. }
  345. return Center(
  346. child: LoadingListPage(),
  347. );
  348. },
  349. );
  350. }
  351. @override
  352. void dispose() {
  353. _scrollController.dispose();
  354. super.dispose();
  355. }
  356. }
  357. class ItemInfinityWidget extends StatelessWidget {
  358. final List<Activities> currentItems;
  359. final Activities item;
  360. final int currentPage;
  361. final bool currentReachedMax;
  362. const ItemInfinityWidget(
  363. {Key key,
  364. @required this.currentItems,
  365. @required this.item,
  366. @required this.currentPage,
  367. @required this.currentReachedMax})
  368. : super(key: key);
  369. @override
  370. Widget build(BuildContext context) {
  371. return GestureDetector(
  372. child: Card(
  373. child: ListTile(
  374. title: Text(item.activityTypeDescription ?? ''),
  375. subtitle: Text(item.executeDate.format_DDMMYY_HHmm()),
  376. ),
  377. ),
  378. onTap: () {
  379. if (item.activityTypeName == "ACTIVE_TYPE_NURSERY") {
  380. Get.to(EditActionNurseryScreen(
  381. cropId: item.cropId,
  382. activityId: item.id,
  383. isEdit: true,
  384. ));
  385. } else if (item.activityTypeName == "ACTIVE_TYPE_STATUS_CROP") {
  386. Get.to(EditActionCropStatusScreen(
  387. cropId: item.cropId,
  388. activityId: item.id,
  389. isEdit: true,
  390. ));
  391. } else if (item.activityTypeName == "ACTIVE_TYPE_UPDATE_ENV") {
  392. Get.to(EditActionEnvironmentUpdate(
  393. cropId: item.cropId,
  394. activityId: item.id,
  395. isEdit: true,
  396. ));
  397. } else if (item.activityTypeName ==
  398. "ACTIVE_TYPE_PESTS_INVESTIGATION") {
  399. Get.to(EditActionDiseaseScreen(
  400. cropId: item.cropId,
  401. activityId: item.id,
  402. isEdit: true,
  403. ));
  404. } else if (item.activityTypeName == "ACTIVE_TYPE_USE_WATER") {
  405. Get.to(EditActionUseWaterScreen(
  406. cropId: item.cropId,
  407. activityId: item.id,
  408. isEdit: true,
  409. ));
  410. } else if (item.activityTypeName == "ACTIVE_TYPE_HARVEST") {
  411. Get.to(EditActionHarvestScreen(
  412. cropId: item.cropId,
  413. activityId: item.id,
  414. isEdit: true,
  415. ));
  416. } else if (item.activityTypeName == "ACTIVE_TYPE_PACKING") {
  417. Get.to(EditActionPackingScreen(
  418. cropId: item.cropId,
  419. activityId: item.id,
  420. isEdit: true,
  421. ));
  422. } else if (item.activityTypeName == "ACTIVE_TYPE_SELL") {
  423. Get.to(EditActionSellScreen(
  424. cropId: item.cropId,
  425. activityId: item.id,
  426. isEdit: true,
  427. ));
  428. } else if (item.activityTypeName == "ACTIVE_TYPE_END") {
  429. Get.to(EditActionEndScreen(
  430. cropId: item.cropId,
  431. activityId: item.id,
  432. isEdit: true,
  433. ));
  434. } else if (item.activityTypeName == "ACTIVE_TYPE_STATUS_GROW") {
  435. Get.to(EditActionPlantScreen(
  436. cropId: item.cropId,
  437. activityId: item.id,
  438. isEdit: true,
  439. ));
  440. } else if (item.activityTypeName == "ACTIVE_TYPE_MANURING") {
  441. Get.to(EditActionDungScreen(
  442. cropId: item.cropId,
  443. activityId: item.id,
  444. isEdit: true,
  445. ));
  446. } else if (item.activityTypeName == "ACTIVE_TYPE_SPRAY") {
  447. Get.to(EditActionSprayingScreen(
  448. cropId: item.cropId,
  449. activityId: item.id,
  450. isEdit: true,
  451. ));
  452. } else if (item.activityTypeName == "ACTIVE_TYPE_PROCESS") {
  453. Get.to(EditActionHarvestProcessScreen(
  454. cropId: item.cropId,
  455. activityId: item.id,
  456. isEdit: true,
  457. ));
  458. } else {
  459. Get.to(EditActionOtherScreen(
  460. cropId: item.cropId,
  461. activityId: item.id,
  462. isEdit: true,
  463. ));
  464. }
  465. });
  466. }
  467. }
  468. class ActionType {
  469. Widget listScreen;
  470. String actionName;
  471. ActionType(String actionName, Widget listScreen) {
  472. this.actionName = actionName;
  473. this.listScreen = listScreen;
  474. }
  475. }