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.

271 lines
9.1KB

  1. import 'package:farm_tpf/custom_model/CropPlot.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/bottom_loader.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  6. import 'package:farm_tpf/presentation/screens/actions/other/sc_edit_action_other.dart';
  7. import 'package:farm_tpf/presentation/screens/plot/sc_plot.dart';
  8. import 'package:farm_tpf/presentation/screens/plot_detail/bloc/plot_detail_bloc.dart';
  9. import 'package:farm_tpf/utils/const_color.dart';
  10. import 'package:farm_tpf/utils/const_string.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_bloc/flutter_bloc.dart';
  13. import 'package:farm_tpf/utils/formatter.dart';
  14. class PlotActionScreen extends StatefulWidget {
  15. final int cropId;
  16. PlotActionScreen({@required this.cropId});
  17. @override
  18. _PlotActionScreenState createState() => _PlotActionScreenState();
  19. }
  20. class _PlotActionScreenState extends State<PlotActionScreen> {
  21. List<ActionType> actions = new List<ActionType>();
  22. ScrollController _scrollController;
  23. @override
  24. void initState() {
  25. super.initState();
  26. _scrollController = ScrollController()..addListener(() => setState(() {}));
  27. _initActionButtons();
  28. }
  29. _initActionButtons() {
  30. actions.add(ActionType(plot_action_nursery, null, PlotListScreen()));
  31. actions.add(ActionType(plot_action_plant, null, null));
  32. actions.add(ActionType(plot_action_crop_status, null, null));
  33. actions.add(ActionType(plot_action_environment_update, null, null));
  34. actions.add(ActionType(plot_action_dung, null, null));
  35. actions.add(ActionType(plot_action_spraying, null, null));
  36. actions.add(ActionType(plot_action_disease, null, null));
  37. actions.add(ActionType(plot_action_use_water, null, null));
  38. actions.add(ActionType(plot_action_other, null, EditActionOtherScreen()));
  39. actions.add(ActionType(plot_action_harvest, null, null));
  40. actions.add(ActionType(plot_action_finish, null, null));
  41. }
  42. Widget _createActionButtons(ActionType actionType) {
  43. return GestureDetector(
  44. onTap: () {
  45. Navigator.of(context).push(
  46. MaterialPageRoute(builder: (context) => actionType.listScreen));
  47. },
  48. child: Container(
  49. height: 75,
  50. margin: EdgeInsets.all(4.0),
  51. padding: EdgeInsets.all(0.0),
  52. decoration: BoxDecoration(
  53. color: COLOR_CONST.WHITE,
  54. borderRadius: BorderRadius.only(
  55. topLeft: Radius.circular(8.0),
  56. bottomLeft: Radius.circular(8.0),
  57. bottomRight: Radius.circular(8.0),
  58. topRight: Radius.circular(8.0)),
  59. boxShadow: <BoxShadow>[
  60. BoxShadow(
  61. color: COLOR_CONST.GRAY1.withOpacity(0.2),
  62. offset: Offset(1.1, 1.1),
  63. blurRadius: 10.0),
  64. ],
  65. ),
  66. child: Stack(
  67. children: <Widget>[
  68. Positioned(
  69. top: -10,
  70. right: -3,
  71. child: (actionType.addScreen == null)
  72. ? Container()
  73. : IconButton(
  74. icon: Icon(
  75. Icons.add_circle,
  76. size: 40,
  77. color: Colors.green,
  78. ),
  79. onPressed: () {
  80. Navigator.of(context).push(MaterialPageRoute(
  81. builder: (context) => actionType.addScreen));
  82. })),
  83. Positioned.fill(
  84. child: Align(
  85. alignment: Alignment.center,
  86. child: Text(
  87. actionType.actionName,
  88. textAlign: TextAlign.center,
  89. style: TextStyle(
  90. fontWeight: FontWeight.w400,
  91. fontSize: 13,
  92. color: COLOR_CONST.BLACK2,
  93. ),
  94. )),
  95. ),
  96. ],
  97. ),
  98. ));
  99. }
  100. bool _showTitle(BuildContext context) {
  101. var kExpandedHeight = MediaQuery.of(context).size.width * 1.125 + 32;
  102. return _scrollController.hasClients &&
  103. _scrollController.offset > kExpandedHeight - kToolbarHeight;
  104. }
  105. @override
  106. Widget build(BuildContext context) {
  107. return NestedScrollView(
  108. controller: _scrollController,
  109. headerSliverBuilder: (context, innerBoxScrolled) => [
  110. SliverAppBar(
  111. floating: false,
  112. pinned: true,
  113. backgroundColor: Colors.white,
  114. leading: Container(),
  115. title: _showTitle(context) ? Text(plot_detail_title) : null,
  116. //Height flexibleSpace : WidthScreen /2 * 6/16 * 6(row) + 8(space) *4
  117. expandedHeight: MediaQuery.of(context).size.width * 1.125 + 32,
  118. flexibleSpace: _showTitle(context)
  119. ? null
  120. : FlexibleSpaceBar(
  121. centerTitle: true,
  122. title: GridView.count(
  123. shrinkWrap: true,
  124. crossAxisCount: 2,
  125. childAspectRatio: 16 / 6,
  126. children: actions.map(
  127. (item) {
  128. return _createActionButtons(item);
  129. },
  130. ).toList()),
  131. ),
  132. ),
  133. SliverList(
  134. delegate: SliverChildListDelegate([
  135. Container(
  136. height: 40,
  137. color: COLOR_CONST.WHITE_50,
  138. alignment: Alignment.center,
  139. child: _showTitle(context)
  140. ? Text("")
  141. : Text(
  142. plot_detail_title,
  143. style: TextStyle(
  144. fontSize: 20, fontWeight: FontWeight.normal),
  145. ))
  146. ]))
  147. ],
  148. body: BlocProvider(
  149. create: (context) => PlotDetailBloc(repository: Repository())
  150. ..add(DataFetched(widget.cropId)),
  151. child: HoldInfinityWidget(
  152. cropId: widget.cropId,
  153. ),
  154. ),
  155. );
  156. }
  157. }
  158. class HoldInfinityWidget extends StatelessWidget {
  159. final int cropId;
  160. HoldInfinityWidget({@required this.cropId});
  161. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  162. @override
  163. Widget build(BuildContext context) {
  164. return Scaffold(key: _scaffoldKey, body: InfinityView(cropId: cropId));
  165. }
  166. }
  167. class InfinityView extends StatefulWidget {
  168. final int cropId;
  169. InfinityView({@required this.cropId});
  170. @override
  171. _InfinityViewState createState() => _InfinityViewState();
  172. }
  173. class _InfinityViewState extends State<InfinityView> {
  174. final _scrollController = ScrollController();
  175. final _scrollThreshold = 250.0;
  176. PlotDetailBloc _plotDetailBloc;
  177. @override
  178. void initState() {
  179. _scrollController.addListener(() {
  180. final maxScroll = _scrollController.position.maxScrollExtent;
  181. final currentScroll = _scrollController.position.pixels;
  182. if (maxScroll - currentScroll < _scrollThreshold) {
  183. _plotDetailBloc.add(DataFetched(widget.cropId));
  184. }
  185. });
  186. _plotDetailBloc = BlocProvider.of<PlotDetailBloc>(context);
  187. super.initState();
  188. }
  189. @override
  190. Widget build(BuildContext context) {
  191. return BlocBuilder<PlotDetailBloc, PlotDetailState>(
  192. builder: (context, state) {
  193. if (state is PlotDetailFailure) {
  194. return Center(child: Text(state.errorString));
  195. }
  196. if (state is PlotDetailSuccess) {
  197. if (state.items.isEmpty) {
  198. return Center(child: Text(label_list_empty));
  199. }
  200. return RefreshIndicator(
  201. child: ListView.builder(
  202. physics: AlwaysScrollableScrollPhysics(),
  203. itemBuilder: (BuildContext context, int index) {
  204. return index >= state.items.length
  205. ? BottomLoader()
  206. : ItemInfinityWidget(item: state.items[index]);
  207. },
  208. itemCount: state.hasReachedMax
  209. ? state.items.length
  210. : state.items.length + 1,
  211. controller: _scrollController,
  212. ),
  213. onRefresh: () async {
  214. _plotDetailBloc.add(OnRefresh(widget.cropId));
  215. });
  216. }
  217. return Center(
  218. child: LoadingListPage(),
  219. );
  220. },
  221. );
  222. }
  223. @override
  224. void dispose() {
  225. _scrollController.dispose();
  226. super.dispose();
  227. }
  228. }
  229. class ItemInfinityWidget extends StatelessWidget {
  230. final Activities item;
  231. const ItemInfinityWidget({Key key, @required this.item}) : super(key: key);
  232. @override
  233. Widget build(BuildContext context) {
  234. return GestureDetector(
  235. child: Card(
  236. child: ListTile(
  237. title: Text(item.activityTypeName),
  238. subtitle: Text(item.executeDate.format_DDMMYY_HHmm()),
  239. ),
  240. ),
  241. onTap: () {});
  242. }
  243. }
  244. class ActionType {
  245. Widget addScreen;
  246. Widget listScreen;
  247. String actionName;
  248. ActionType(String actionName, Widget addScreen, Widget listScreen) {
  249. this.actionName = actionName;
  250. this.addScreen = addScreen;
  251. this.listScreen = listScreen;
  252. }
  253. }