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.

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