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.

289 lines
10KB

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