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.

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