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.

273 lines
9.3KB

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