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.

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