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.

348 lines
11KB

  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/utils/const_assets.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:farm_tpf/utils/formatter.dart';
  21. import 'package:get/get.dart';
  22. import 'bloc/plot_bloc.dart';
  23. class PlotListScreen extends StatefulWidget {
  24. @override
  25. _PlotListScreenState createState() => _PlotListScreenState();
  26. }
  27. class _PlotListScreenState extends State<PlotListScreen> {
  28. UserRepository _userRepository = UserRepository();
  29. final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  30. var pref = LocalPref();
  31. var token;
  32. var client;
  33. String pushkey = "";
  34. String currentFullName = "";
  35. Future<Null> getSharedPrefs() async {
  36. token = await pref.getString(DATA_CONST.TOKEN_KEY);
  37. pushkey = await pref.getString(DATA_CONST.PUSH_KEY);
  38. currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  39. var options = BaseOptions(baseUrl: ConstCommon.baseUrl);
  40. options.headers["Authorization"] = "Bearer $token";
  41. client = Dio(options);
  42. if (Platform.isIOS) {
  43. _firebaseMessaging
  44. .requestNotificationPermissions(IosNotificationSettings());
  45. }
  46. _firebaseMessaging.configure(
  47. onMessage: (Map<String, dynamic> message) async {
  48. print("onMessage---: $message");
  49. },
  50. onBackgroundMessage: Platform.isIOS ? null : myBackgroundMessageHandler,
  51. onLaunch: (Map<String, dynamic> message) async {
  52. print("onLaunch: $message");
  53. Future.delayed(Duration(milliseconds: 500), () {
  54. _notificationNavigateOnFCM(message);
  55. });
  56. },
  57. onResume: (Map<String, dynamic> message) async {
  58. print("onResume: $message");
  59. _notificationNavigateOnFCM(message);
  60. },
  61. );
  62. _firebaseMessaging.requestNotificationPermissions(
  63. const IosNotificationSettings(
  64. sound: true, badge: true, alert: true, provisional: true));
  65. _firebaseMessaging.onIosSettingsRegistered
  66. .listen((IosNotificationSettings settings) {
  67. print("Settings registered: $settings");
  68. });
  69. if (pushkey?.isEmpty ?? true) {
  70. _firebaseMessaging.getToken().then((String token) {
  71. assert(token != null);
  72. print("Push Messaging token: $token");
  73. _userRepository.updateFcmToken(token).then((value) {
  74. print("send push key successful");
  75. pref.saveString(DATA_CONST.PUSH_KEY, token);
  76. });
  77. // client.put("");
  78. });
  79. } else {
  80. print("Don't need get push key");
  81. }
  82. if (currentFullName?.isEmpty ?? true) {
  83. try {
  84. var currentUser = await _userRepository.getUser();
  85. pref.saveString(DATA_CONST.CURRENT_FULL_NAME, currentUser.fullName);
  86. print("fullname: ${currentUser.fullName}");
  87. } catch (e) {
  88. print("error: ${e.toString()}");
  89. }
  90. }
  91. }
  92. _notificationNavigateOnFCM(Map<String, dynamic> message) {
  93. //parse data difference between Ios and Android
  94. var noti;
  95. if (Platform.isAndroid) {
  96. var data = message['data'];
  97. noti = NotificationDTO()
  98. ..contents = data['contents']
  99. ..tbCropId = data['tbCropId']
  100. ..type = data['type'];
  101. } else {
  102. noti = NotificationDTO.fromJson(message);
  103. }
  104. if (noti.contents == "ENV_UPDATE") {
  105. Get.to(PlotDetailScreen(
  106. cropType: noti.type,
  107. cropId: noti.tbCropId,
  108. initialIndex: 0,
  109. ));
  110. } else if (noti.contents == "PIC_UPDATE") {
  111. Get.to(PlotDetailScreen(
  112. cropType: noti.type,
  113. cropId: noti.tbCropId,
  114. initialIndex: 1,
  115. ));
  116. } else {
  117. //Go home
  118. }
  119. }
  120. @override
  121. void initState() {
  122. super.initState();
  123. // getSharedPrefs();
  124. }
  125. @override
  126. Widget build(BuildContext context) {
  127. return BlocProvider(
  128. create: (context) =>
  129. PlotBloc(repository: Repository())..add(DataFetched()),
  130. child: HoldInfinityWidget(),
  131. );
  132. }
  133. }
  134. class HoldInfinityWidget extends StatelessWidget {
  135. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  136. @override
  137. Widget build(BuildContext context) {
  138. return Scaffold(
  139. backgroundColor: Colors.white,
  140. key: _scaffoldKey,
  141. body: SafeArea(child: InfinityView()));
  142. }
  143. }
  144. class InfinityView extends StatefulWidget {
  145. @override
  146. _InfinityViewState createState() => _InfinityViewState();
  147. }
  148. class _InfinityViewState extends State<InfinityView> {
  149. final _scrollController = ScrollController();
  150. final _scrollThreshold = 250.0;
  151. PlotBloc _plotBloc;
  152. @override
  153. void initState() {
  154. _scrollController.addListener(() {
  155. final maxScroll = _scrollController.position.maxScrollExtent;
  156. final currentScroll = _scrollController.position.pixels;
  157. if (maxScroll - currentScroll < _scrollThreshold) {
  158. _plotBloc.add(DataFetched());
  159. }
  160. });
  161. _plotBloc = BlocProvider.of<PlotBloc>(context);
  162. super.initState();
  163. }
  164. @override
  165. Widget build(BuildContext context) {
  166. return Column(
  167. crossAxisAlignment: CrossAxisAlignment.start,
  168. children: <Widget>[
  169. SizedBox(
  170. height: 8,
  171. ),
  172. Container(
  173. padding: EdgeInsets.all(8),
  174. color: Colors.white,
  175. child: Text(
  176. 'Danh sách lô trồng',
  177. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  178. )),
  179. WidgetSearch(),
  180. Expanded(child: BlocBuilder<PlotBloc, PlotState>(
  181. builder: (context, state) {
  182. if (state is PlotFailure) {
  183. return Center(child: Text(state.errorString));
  184. }
  185. if (state is PlotSuccess) {
  186. if (state.items.isEmpty) {
  187. return Center(child: Text(label_list_empty));
  188. }
  189. return RefreshIndicator(
  190. child: ListView.builder(
  191. physics: AlwaysScrollableScrollPhysics(),
  192. itemBuilder: (BuildContext context, int index) {
  193. return index >= state.items.length
  194. ? BottomLoader()
  195. : ItemInfinityWidget(item: state.items[index]);
  196. },
  197. itemCount: state.hasReachedMax
  198. ? state.items.length
  199. : state.items.length + 1,
  200. controller: _scrollController,
  201. ),
  202. onRefresh: () async {
  203. _plotBloc.add(OnRefresh());
  204. });
  205. }
  206. return Center(
  207. child: LoadingListPage(),
  208. );
  209. },
  210. ))
  211. ],
  212. );
  213. }
  214. @override
  215. void dispose() {
  216. _scrollController.dispose();
  217. super.dispose();
  218. }
  219. }
  220. class ItemInfinityWidget extends StatelessWidget {
  221. final Crop item;
  222. const ItemInfinityWidget({Key key, @required this.item}) : super(key: key);
  223. @override
  224. Widget build(BuildContext context) {
  225. var backgroundColor;
  226. var textColor;
  227. switch (item.status) {
  228. case "STATUS_ARE_ACTIVE":
  229. backgroundColor = Colors.white;
  230. textColor = AppColors.DEFAULT;
  231. break;
  232. case "STATUS_FINISHED":
  233. backgroundColor = AppColors.DEFAULT;
  234. textColor = Colors.white;
  235. break;
  236. default:
  237. backgroundColor = Colors.white;
  238. textColor = Colors.black;
  239. }
  240. return GestureDetector(
  241. child: Container(
  242. margin: EdgeInsets.all(8),
  243. decoration: BoxDecoration(
  244. color: backgroundColor,
  245. border: Border.all(color: Colors.grey[300], width: 0.35),
  246. borderRadius: BorderRadius.circular(8),
  247. boxShadow: [
  248. BoxShadow(
  249. color: Colors.grey[300],
  250. blurRadius: 3,
  251. offset: Offset(0, 3))
  252. ]),
  253. padding: EdgeInsets.all(8),
  254. child: Row(
  255. children: [
  256. Container(
  257. child: Stack(
  258. children: [
  259. Image.asset(
  260. AppAssets.tempImage,
  261. width: 65,
  262. height: 65,
  263. ),
  264. Positioned(
  265. child: Container(
  266. color: Colors.grey.withOpacity(0.5),
  267. width: 65,
  268. height: 20,
  269. child: Text(
  270. item.areaM2.formatNumtoStringDecimal().toString() +
  271. " m\u00B2",
  272. textAlign: TextAlign.center,
  273. style: TextStyle(color: Colors.white)),
  274. ),
  275. bottom: 0,
  276. )
  277. ],
  278. ),
  279. ),
  280. SizedBox(
  281. width: 12,
  282. ),
  283. Expanded(
  284. child: Container(
  285. height: 75,
  286. child: Column(
  287. crossAxisAlignment: CrossAxisAlignment.start,
  288. mainAxisSize: MainAxisSize.min,
  289. children: [
  290. Text("${item.code ?? ''} - ${item.suppliesName ?? ''}",
  291. style: TextStyle(
  292. color: textColor, fontWeight: FontWeight.bold)),
  293. Expanded(
  294. child: SizedBox(),
  295. ),
  296. Row(
  297. children: [
  298. Icon(
  299. Icons.access_time,
  300. size: 16,
  301. color: textColor,
  302. ),
  303. SizedBox(
  304. width: 4,
  305. ),
  306. Expanded(
  307. child: Text(
  308. item.startDate.format_DDMMYY_HHmm().toString(),
  309. style: TextStyle(color: textColor)),
  310. ),
  311. ],
  312. )
  313. ],
  314. ),
  315. ),
  316. )
  317. ],
  318. ),
  319. ),
  320. onTap: () {
  321. Navigator.push(
  322. context,
  323. MaterialPageRoute(
  324. builder: (BuildContext context) => PlotDetailScreen(
  325. cropId: item.id, initialIndex: 0, cropType: item.type)));
  326. });
  327. }
  328. }