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.

441 lines
16KB

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