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.

281 lines
8.8KB

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