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.

431 lines
15KB

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