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.

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