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.

275 lines
9.4KB

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