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.

521 lines
18KB

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