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.

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