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.

400 lines
14KB

  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. import 'package:get/get.dart';
  24. class PlotActionScreen extends StatefulWidget {
  25. int cropId;
  26. String cropCode;
  27. PlotActionScreen({this.cropId, this.cropCode});
  28. @override
  29. _PlotActionScreenState createState() => _PlotActionScreenState();
  30. }
  31. class _PlotActionScreenState extends State<PlotActionScreen> {
  32. List<ActionType> actions = new List<ActionType>();
  33. ScrollController _scrollController;
  34. var changeToRefresh = Get.put(ChangeToRefreshLists());
  35. @override
  36. void initState() {
  37. super.initState();
  38. changeToRefresh.initValue();
  39. _scrollController = ScrollController()..addListener(() => setState(() {}));
  40. _initActionButtons();
  41. }
  42. _initActionButtons() {
  43. actions.add(ActionType(
  44. plot_action_nursery,
  45. null,
  46. EditActionNurseryScreen(
  47. cropId: widget.cropId,
  48. )));
  49. actions.add(ActionType(plot_action_plant, null, EditActionPlantScreen()));
  50. actions.add(ActionType(
  51. plot_action_crop_status, null, EditActionCropStatusScreen()));
  52. actions.add(ActionType(
  53. plot_action_environment_update, null, EditActionEnvironmentUpdate()));
  54. actions.add(ActionType(plot_action_dung, null, EditActionDungScreen()));
  55. actions.add(
  56. ActionType(plot_action_spraying, null, EditActionSprayingScreen()));
  57. actions
  58. .add(ActionType(plot_action_disease, null, EditActionDiseaseScreen()));
  59. actions.add(
  60. ActionType(plot_action_use_water, null, EditActionUseWaterScreen()));
  61. actions.add(ActionType(plot_action_other, null, EditActionOtherScreen()));
  62. actions
  63. .add(ActionType(plot_action_harvest, null, EditActionHarvestScreen()));
  64. actions.add(ActionType(plot_action_finish, null, EditActionEndScreen()));
  65. }
  66. Widget _createActionButtons(ActionType actionType, BuildContext _context) {
  67. return BlocProvider<PlotDetailBloc>(
  68. create: (context) => PlotDetailBloc(repository: Repository()),
  69. child: GestureDetector(
  70. onTap: () {
  71. Navigator.of(context)
  72. .push(MaterialPageRoute(
  73. builder: (context) => actionType.listScreen))
  74. .then((value) {
  75. if (1 == 1) {
  76. try {
  77. //TODO: refresh list
  78. } catch (e) {
  79. print(e.toString());
  80. }
  81. }
  82. });
  83. },
  84. child: Container(
  85. height: 75,
  86. margin: EdgeInsets.all(4.0),
  87. padding: EdgeInsets.all(0.0),
  88. decoration: BoxDecoration(
  89. color: COLOR_CONST.WHITE,
  90. borderRadius: BorderRadius.only(
  91. topLeft: Radius.circular(8.0),
  92. bottomLeft: Radius.circular(8.0),
  93. bottomRight: Radius.circular(8.0),
  94. topRight: Radius.circular(8.0)),
  95. boxShadow: <BoxShadow>[
  96. BoxShadow(
  97. color: COLOR_CONST.GRAY1.withOpacity(0.2),
  98. offset: Offset(1.1, 1.1),
  99. blurRadius: 10.0),
  100. ],
  101. ),
  102. child: Stack(
  103. children: <Widget>[
  104. Positioned(
  105. top: -10,
  106. right: -3,
  107. child: (actionType.addScreen == null)
  108. ? Container()
  109. : IconButton(
  110. icon: Icon(
  111. Icons.add_circle,
  112. size: 40,
  113. color: Colors.green,
  114. ),
  115. onPressed: () {
  116. Navigator.of(context).push(MaterialPageRoute(
  117. builder: (context) => actionType.addScreen));
  118. })),
  119. Positioned.fill(
  120. child: Align(
  121. alignment: Alignment.center,
  122. child: Text(
  123. actionType.actionName,
  124. textAlign: TextAlign.center,
  125. style: TextStyle(
  126. fontWeight: FontWeight.w400,
  127. fontSize: 13,
  128. color: COLOR_CONST.BLACK2,
  129. ),
  130. )),
  131. ),
  132. ],
  133. ),
  134. )),
  135. );
  136. }
  137. bool _showTitle(BuildContext context) {
  138. var kExpandedHeight = MediaQuery.of(context).size.width * 1.125 + 32;
  139. return _scrollController.hasClients &&
  140. _scrollController.offset > kExpandedHeight - kToolbarHeight;
  141. }
  142. @override
  143. Widget build(BuildContext context) {
  144. return NestedScrollView(
  145. controller: _scrollController,
  146. headerSliverBuilder: (context, innerBoxScrolled) => [
  147. SliverAppBar(
  148. floating: false,
  149. pinned: false,
  150. backgroundColor: Colors.white,
  151. leading: Container(),
  152. title: null,
  153. // title: _showTitle(context) ? Text(plot_detail_title) : null,
  154. //Height flexibleSpace : WidthScreen /2 * 6/16 * 6(row) + 8(space) *4
  155. expandedHeight: MediaQuery.of(context).size.width * 1.125 + 32,
  156. flexibleSpace: _showTitle(context)
  157. ? null
  158. : BlocProvider<PlotDetailBloc>(
  159. create: (context) => PlotDetailBloc(repository: Repository()),
  160. child: BlocBuilder<PlotDetailBloc, PlotDetailState>(
  161. builder: (contextB, state) {
  162. return FlexibleSpaceBar(
  163. centerTitle: true,
  164. title: GridView.count(
  165. shrinkWrap: true,
  166. crossAxisCount: 2,
  167. childAspectRatio: 16 / 6,
  168. children: actions.map(
  169. (item) {
  170. return _createActionButtons(item, contextB);
  171. },
  172. ).toList()),
  173. );
  174. }),
  175. ),
  176. ),
  177. ],
  178. body: BlocProvider(
  179. create: (context) => PlotDetailBloc(repository: Repository())
  180. ..add(DataFetched(cropId: widget.cropId, cropCode: widget.cropCode)),
  181. child: HoldInfinityWidget(
  182. cropId: widget.cropId,
  183. cropCode: widget.cropCode,
  184. ),
  185. ),
  186. );
  187. }
  188. }
  189. class HoldInfinityWidget extends StatelessWidget {
  190. int cropId;
  191. String cropCode;
  192. HoldInfinityWidget({this.cropId, this.cropCode});
  193. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  194. @override
  195. Widget build(BuildContext context) {
  196. return Scaffold(key: _scaffoldKey, body: InfinityView(cropId: cropId));
  197. }
  198. }
  199. class InfinityView extends StatefulWidget {
  200. int cropId;
  201. String cropCode;
  202. InfinityView({this.cropId, this.cropCode});
  203. @override
  204. _InfinityViewState createState() => _InfinityViewState();
  205. }
  206. class _InfinityViewState extends State<InfinityView> {
  207. final _scrollController = ScrollController();
  208. final _scrollThreshold = 250.0;
  209. PlotDetailBloc _plotDetailBloc;
  210. var a = Get.put(ChangeToRefreshLists());
  211. @override
  212. void initState() {
  213. _scrollController.addListener(() {
  214. final maxScroll = _scrollController.position.maxScrollExtent;
  215. final currentScroll = _scrollController.position.pixels;
  216. if (maxScroll - currentScroll < _scrollThreshold) {
  217. _plotDetailBloc
  218. .add(DataFetched(cropId: widget.cropId, cropCode: widget.cropCode));
  219. }
  220. });
  221. _plotDetailBloc = BlocProvider.of<PlotDetailBloc>(context);
  222. super.initState();
  223. }
  224. @override
  225. Widget build(BuildContext context) {
  226. return BlocBuilder<PlotDetailBloc, PlotDetailState>(
  227. builder: (context, state) {
  228. if (state is PlotDetailFailure) {
  229. return Center(child: Text(state.errorString));
  230. }
  231. if (state is PlotDetailSuccess) {
  232. if (state.items.isEmpty) {
  233. return Center(child: Text(label_list_empty));
  234. }
  235. List<Activities> currentItems = List<Activities>.from(state.items);
  236. Get.find<ChangeToRefreshLists>()
  237. .updateValue(currentItems, state.page, state.hasReachedMax);
  238. return RefreshIndicator(
  239. child: Column(
  240. children: [
  241. Container(
  242. height: 40,
  243. alignment: Alignment.center,
  244. decoration: BoxDecoration(
  245. color: COLOR_CONST.WHITE_50,
  246. border: Border(
  247. top: BorderSide(
  248. width: 0.5, color: COLOR_CONST.DEFAULT),
  249. bottom: BorderSide(
  250. width: 0.5, color: COLOR_CONST.DEFAULT)),
  251. ),
  252. child: Text(
  253. plot_detail_title,
  254. style: TextStyle(
  255. fontSize: 20, fontWeight: FontWeight.normal),
  256. )),
  257. Expanded(
  258. child: ListView.builder(
  259. physics: AlwaysScrollableScrollPhysics(),
  260. itemBuilder: (BuildContext context, int index) {
  261. return index >= state.items.length
  262. ? BottomLoader()
  263. : ItemInfinityWidget(
  264. currentItems: currentItems,
  265. item: state.items[index],
  266. currentPage: state.page,
  267. currentReachedMax: state.hasReachedMax);
  268. },
  269. itemCount: state.hasReachedMax
  270. ? state.items.length
  271. : state.items.length + 1,
  272. controller: _scrollController,
  273. ))
  274. ],
  275. ),
  276. onRefresh: () async {
  277. _plotDetailBloc.add(OnRefresh(
  278. cropId: widget.cropId, cropCode: widget.cropCode));
  279. });
  280. }
  281. return Center(
  282. child: LoadingListPage(),
  283. );
  284. },
  285. );
  286. }
  287. @override
  288. void dispose() {
  289. _scrollController.dispose();
  290. super.dispose();
  291. }
  292. }
  293. class ItemInfinityWidget extends StatelessWidget {
  294. final List<Activities> currentItems;
  295. final Activities item;
  296. final int currentPage;
  297. final bool currentReachedMax;
  298. const ItemInfinityWidget(
  299. {Key key,
  300. @required this.currentItems,
  301. @required this.item,
  302. @required this.currentPage,
  303. @required this.currentReachedMax})
  304. : super(key: key);
  305. @override
  306. Widget build(BuildContext context) {
  307. return GestureDetector(
  308. child: Card(
  309. child: ListTile(
  310. title: Text(item.activityTypeDescription ?? ''),
  311. subtitle: Text(item.executeDate.format_DDMMYY_HHmm()),
  312. trailing: Text(item.id.toString()),
  313. ),
  314. ),
  315. onTap: () {
  316. if (item.activityTypeName == "ACTIVE_TYPE_NURSERY") {
  317. Get.to(EditActionNurseryScreen(
  318. cropId: item.cropId,
  319. activityId: item.id,
  320. isEdit: true,
  321. )).then((value) {
  322. if (value != null) {
  323. try {
  324. //TODO: refresh when edit activity
  325. // BlocProvider.of<PlotDetailBloc>(context)
  326. // .add(OnRefresh(cropId: item.cropId));
  327. // var updatedItem = Activities.fromJson(value);
  328. // List<Activities> updatedItems = new List<Activities>();
  329. // currentItems.forEach((e) {
  330. // if (e.id == updatedItem.id) {
  331. // e.executeDate = updatedItem.executeDate;
  332. // } else {
  333. // //
  334. // }
  335. // updatedItems.add(Activities.clone(e));
  336. // });
  337. // BlocProvider.of<PlotDetailBloc>(context).add(
  338. // OnUpdate<Activities>(
  339. // currentItems: updatedItems,
  340. // currentPage: currentPage,
  341. // hasReachedMax: currentReachedMax));
  342. } catch (e) {
  343. print(e.toString());
  344. }
  345. }
  346. });
  347. }
  348. });
  349. }
  350. }
  351. class ActionType {
  352. Widget addScreen;
  353. Widget listScreen;
  354. String actionName;
  355. ActionType(String actionName, Widget addScreen, Widget listScreen) {
  356. this.actionName = actionName;
  357. this.addScreen = addScreen;
  358. this.listScreen = listScreen;
  359. }
  360. }
  361. class ChangeToRefreshLists extends GetxController {
  362. List<Activities> currentItems;
  363. int currentPage;
  364. bool currentReachedMax;
  365. void initValue() {
  366. currentItems = List<Activities>();
  367. currentPage = 0;
  368. currentReachedMax = true;
  369. update();
  370. }
  371. void updateValue(List<Activities> updateItems, int page, bool reachedMax) {
  372. currentItems = updateItems;
  373. currentPage = page;
  374. currentReachedMax = reachedMax;
  375. update();
  376. }
  377. }