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.

350 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/app_bar_widget.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  11. import 'package:farm_tpf/presentation/screens/plot/widget_search.dart';
  12. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart';
  13. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_information.dart';
  14. import 'package:farm_tpf/utils/const_assets.dart';
  15. import 'package:farm_tpf/utils/const_color.dart';
  16. import 'package:farm_tpf/utils/const_common.dart';
  17. import 'package:farm_tpf/utils/pref.dart';
  18. import 'package:firebase_messaging/firebase_messaging.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter_bloc/flutter_bloc.dart';
  21. import 'package:farm_tpf/utils/const_string.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. backgroundColor: Colors.white,
  139. key: _scaffoldKey,
  140. appBar: AppBarWidget(
  141. isBack: false,
  142. ),
  143. body: InfinityView());
  144. }
  145. }
  146. class InfinityView extends StatefulWidget {
  147. @override
  148. _InfinityViewState createState() => _InfinityViewState();
  149. }
  150. class _InfinityViewState extends State<InfinityView> {
  151. final _scrollController = ScrollController();
  152. final _scrollThreshold = 250.0;
  153. PlotBloc _plotBloc;
  154. @override
  155. void initState() {
  156. _scrollController.addListener(() {
  157. final maxScroll = _scrollController.position.maxScrollExtent;
  158. final currentScroll = _scrollController.position.pixels;
  159. if (maxScroll - currentScroll < _scrollThreshold) {
  160. _plotBloc.add(DataFetched());
  161. }
  162. });
  163. _plotBloc = BlocProvider.of<PlotBloc>(context);
  164. super.initState();
  165. }
  166. @override
  167. Widget build(BuildContext context) {
  168. return Column(
  169. crossAxisAlignment: CrossAxisAlignment.start,
  170. children: <Widget>[
  171. Container(
  172. padding: EdgeInsets.all(8),
  173. color: Colors.white,
  174. child: Text(
  175. 'Danh sách lô trồng',
  176. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  177. )),
  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: Container(
  241. margin: EdgeInsets.all(8),
  242. decoration: BoxDecoration(
  243. color: backgroundColor,
  244. border: Border.all(color: Colors.grey[300], width: 0.35),
  245. borderRadius: BorderRadius.circular(8),
  246. boxShadow: [
  247. BoxShadow(
  248. color: Colors.grey[300],
  249. blurRadius: 3,
  250. offset: Offset(0, 3))
  251. ]),
  252. padding: EdgeInsets.all(8),
  253. child: Row(
  254. children: [
  255. Container(
  256. child: Stack(
  257. children: [
  258. Image.asset(
  259. AppAssets.tempImage,
  260. width: 65,
  261. height: 65,
  262. ),
  263. Positioned(
  264. child: Container(
  265. color: Colors.grey.withOpacity(0.5),
  266. width: 65,
  267. height: 20,
  268. child: Text(
  269. item.areaM2.formatNumtoStringDecimal().toString() +
  270. " m\u00B2",
  271. textAlign: TextAlign.center,
  272. style: TextStyle(color: Colors.white)),
  273. ),
  274. bottom: 0,
  275. )
  276. ],
  277. ),
  278. ),
  279. SizedBox(
  280. width: 12,
  281. ),
  282. Expanded(
  283. child: Container(
  284. height: 75,
  285. child: Column(
  286. crossAxisAlignment: CrossAxisAlignment.start,
  287. mainAxisSize: MainAxisSize.min,
  288. children: [
  289. Text("${item.code ?? ''} - ${item.suppliesName ?? ''}",
  290. style: TextStyle(
  291. color: textColor, fontWeight: FontWeight.bold)),
  292. Expanded(
  293. child: SizedBox(),
  294. ),
  295. Row(
  296. children: [
  297. Icon(
  298. Icons.access_time,
  299. size: 16,
  300. color: textColor,
  301. ),
  302. SizedBox(
  303. width: 4,
  304. ),
  305. Expanded(
  306. child: Text(
  307. item.startDate.format_DDMMYY_HHmm().toString(),
  308. style: TextStyle(color: textColor)),
  309. ),
  310. ],
  311. )
  312. ],
  313. ),
  314. ),
  315. )
  316. ],
  317. ),
  318. ),
  319. onTap: () {
  320. Navigator.push(
  321. context,
  322. MaterialPageRoute(
  323. builder: (BuildContext context) => PlotDetailScreen(
  324. cropId: item.id,
  325. initialIndex: 0,
  326. cropType: item.type,
  327. )));
  328. });
  329. }
  330. }