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.

283 lines
8.9KB

  1. import 'dart:io';
  2. import 'package:dio/dio.dart';
  3. import 'package:farm_tpf/custom_model/NotificationDTO.dart';
  4. import 'package:farm_tpf/data/repository/repository.dart';
  5. import 'package:farm_tpf/data/repository/user_repository.dart';
  6. import 'package:farm_tpf/main.dart';
  7. import 'package:farm_tpf/models/index.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  10. import 'package:farm_tpf/presentation/screens/plot/widget_search.dart';
  11. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart';
  12. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_information.dart';
  13. import 'package:farm_tpf/presentation/screens/tabbar/tabbar.dart';
  14. import 'package:farm_tpf/utils/const_color.dart';
  15. import 'package:farm_tpf/utils/const_common.dart';
  16. import 'package:farm_tpf/utils/pref.dart';
  17. import 'package:firebase_messaging/firebase_messaging.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter_bloc/flutter_bloc.dart';
  20. import 'package:farm_tpf/utils/const_string.dart';
  21. import 'package:font_awesome_flutter/font_awesome_flutter.dart';
  22. import 'package:farm_tpf/utils/formatter.dart';
  23. import 'package:get/get.dart';
  24. import 'bloc/plot_bloc.dart';
  25. class PlotListScreen extends StatefulWidget {
  26. @override
  27. _PlotListScreenState createState() => _PlotListScreenState();
  28. }
  29. class _PlotListScreenState extends State<PlotListScreen> {
  30. UserRepository _userRepository = UserRepository();
  31. final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  32. var pref = LocalPref();
  33. var token;
  34. var client;
  35. String pushkey = "";
  36. String currentFullName = "";
  37. Future<Null> getSharedPrefs() async {
  38. token = await pref.getString(DATA_CONST.TOKEN_KEY);
  39. pushkey = await pref.getString(DATA_CONST.PUSH_KEY);
  40. currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  41. var options = BaseOptions(baseUrl: ConstCommon.baseUrl);
  42. options.headers["Authorization"] = "Bearer $token";
  43. client = Dio(options);
  44. if (Platform.isIOS) {
  45. _firebaseMessaging
  46. .requestNotificationPermissions(IosNotificationSettings());
  47. }
  48. _firebaseMessaging.configure(
  49. onMessage: (Map<String, dynamic> message) async {
  50. print("onMessage: $message");
  51. },
  52. onBackgroundMessage: Platform.isIOS ? null : myBackgroundMessageHandler,
  53. onLaunch: (Map<String, dynamic> message) async {
  54. print("onLaunch: $message");
  55. Future.delayed(Duration(milliseconds: 500), () {
  56. _notificationNavigateOnFCM(message);
  57. });
  58. },
  59. onResume: (Map<String, dynamic> message) async {
  60. print("onResume: $message");
  61. _notificationNavigateOnFCM(message);
  62. },
  63. );
  64. _firebaseMessaging.requestNotificationPermissions(
  65. const IosNotificationSettings(
  66. sound: true, badge: true, alert: true, provisional: true));
  67. _firebaseMessaging.onIosSettingsRegistered
  68. .listen((IosNotificationSettings settings) {
  69. print("Settings registered: $settings");
  70. });
  71. if (pushkey?.isEmpty ?? true) {
  72. _firebaseMessaging.getToken().then((String token) {
  73. assert(token != null);
  74. print("Push Messaging token: $token");
  75. _userRepository.updateFcmToken(token).then((value) {
  76. print("send push key successful");
  77. pref.saveString(DATA_CONST.PUSH_KEY, token);
  78. });
  79. // client.put("");
  80. });
  81. } else {
  82. print("Don't need get push key");
  83. }
  84. if (currentFullName?.isEmpty ?? true) {
  85. try {
  86. var currentUser = await _userRepository.getUser();
  87. pref.saveString(DATA_CONST.CURRENT_FULL_NAME, currentUser.fullName);
  88. print("fullname: ${currentUser.fullName}");
  89. } catch (e) {
  90. print("error: ${e.toString()}");
  91. }
  92. }
  93. }
  94. _notificationNavigateOnFCM(Map<String, dynamic> message) {
  95. //parse data difference between Ios and Android
  96. var noti;
  97. if (Platform.isAndroid) {
  98. var data = message['data'];
  99. noti = NotificationDTO()
  100. ..contents = data['contents']
  101. ..tbCropId = data['tbCropId']
  102. ..type = data['type'];
  103. } else {
  104. noti = NotificationDTO.fromJson(message);
  105. }
  106. if (noti.contents == "ENV_UPDATE") {
  107. Get.to(PlotDetailScreen(
  108. cropId: noti.tbCropId,
  109. cropType: noti.type,
  110. ));
  111. } else if (noti.contents == "PIC_UPDATE") {
  112. Get.to(PlotInformationScreen(
  113. cropId: noti.tbCropId,
  114. ));
  115. } else {
  116. //Go home
  117. }
  118. }
  119. @override
  120. void initState() {
  121. super.initState();
  122. getSharedPrefs();
  123. }
  124. @override
  125. Widget build(BuildContext context) {
  126. return BlocProvider(
  127. create: (context) =>
  128. PlotBloc(repository: Repository())..add(DataFetched()),
  129. child: HoldInfinityWidget(),
  130. );
  131. }
  132. }
  133. class HoldInfinityWidget extends StatelessWidget {
  134. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  135. @override
  136. Widget build(BuildContext context) {
  137. return Scaffold(
  138. key: _scaffoldKey,
  139. appBar: AppBar(
  140. centerTitle: true,
  141. title: Text("Danh sách lô"),
  142. actions: <Widget>[
  143. IconButton(
  144. icon: Icon(FontAwesomeIcons.qrcode),
  145. onPressed: () {
  146. // scan(context);
  147. Get.to(TabbarScreen());
  148. })
  149. ],
  150. ),
  151. body: InfinityView());
  152. }
  153. }
  154. class InfinityView extends StatefulWidget {
  155. @override
  156. _InfinityViewState createState() => _InfinityViewState();
  157. }
  158. class _InfinityViewState extends State<InfinityView> {
  159. final _scrollController = ScrollController();
  160. final _scrollThreshold = 250.0;
  161. PlotBloc _plotBloc;
  162. @override
  163. void initState() {
  164. _scrollController.addListener(() {
  165. final maxScroll = _scrollController.position.maxScrollExtent;
  166. final currentScroll = _scrollController.position.pixels;
  167. if (maxScroll - currentScroll < _scrollThreshold) {
  168. _plotBloc.add(DataFetched());
  169. }
  170. });
  171. _plotBloc = BlocProvider.of<PlotBloc>(context);
  172. super.initState();
  173. }
  174. @override
  175. Widget build(BuildContext context) {
  176. return Column(
  177. children: <Widget>[
  178. WidgetSearch(),
  179. Expanded(child: BlocBuilder<PlotBloc, PlotState>(
  180. builder: (context, state) {
  181. if (state is PlotFailure) {
  182. return Center(child: Text(state.errorString));
  183. }
  184. if (state is PlotSuccess) {
  185. if (state.items.isEmpty) {
  186. return Center(child: Text(label_list_empty));
  187. }
  188. return RefreshIndicator(
  189. child: ListView.builder(
  190. physics: AlwaysScrollableScrollPhysics(),
  191. itemBuilder: (BuildContext context, int index) {
  192. return index >= state.items.length
  193. ? BottomLoader()
  194. : ItemInfinityWidget(item: state.items[index]);
  195. },
  196. itemCount: state.hasReachedMax
  197. ? state.items.length
  198. : state.items.length + 1,
  199. controller: _scrollController,
  200. ),
  201. onRefresh: () async {
  202. _plotBloc.add(OnRefresh());
  203. });
  204. }
  205. return Center(
  206. child: LoadingListPage(),
  207. );
  208. },
  209. ))
  210. ],
  211. );
  212. }
  213. @override
  214. void dispose() {
  215. _scrollController.dispose();
  216. super.dispose();
  217. }
  218. }
  219. class ItemInfinityWidget extends StatelessWidget {
  220. final Crop item;
  221. const ItemInfinityWidget({Key key, @required this.item}) : super(key: key);
  222. @override
  223. Widget build(BuildContext context) {
  224. var backgroundColor;
  225. var textColor;
  226. switch (item.status) {
  227. case "STATUS_ARE_ACTIVE":
  228. backgroundColor = Colors.white;
  229. textColor = AppColors.DEFAULT;
  230. break;
  231. case "STATUS_FINISHED":
  232. backgroundColor = AppColors.DEFAULT;
  233. textColor = Colors.white;
  234. break;
  235. default:
  236. backgroundColor = Colors.white;
  237. textColor = Colors.black;
  238. }
  239. return GestureDetector(
  240. child: Card(
  241. color: backgroundColor,
  242. child: ListTile(
  243. title: Text("${item.code ?? ''} - ${item.suppliesName ?? ''}",
  244. style: TextStyle(color: textColor)),
  245. subtitle: Text(item.startDate.format_DDMMYY_HHmm().toString(),
  246. style: TextStyle(color: textColor)),
  247. trailing: Text(
  248. item.areaM2.formatNumtoStringDecimal().toString() + " m\u00B2",
  249. style: TextStyle(color: textColor)),
  250. ),
  251. ),
  252. onTap: () {
  253. Navigator.push(
  254. context,
  255. MaterialPageRoute(
  256. builder: (BuildContext context) => PlotDetailScreen(
  257. cropId: item.id,
  258. initialIndex: 0,
  259. cropType: item.type,
  260. )));
  261. });
  262. }
  263. }