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.

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