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.

301 lines
11KB

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