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.

465 lines
17KB

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