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