| String? message; | String? message; | ||||
| int? tbCropId; | int? tbCropId; | ||||
| int? tbEntityId; | int? tbEntityId; | ||||
| int? externalId; | |||||
| String? contents; | String? contents; | ||||
| String? createdDate; | String? createdDate; | ||||
| String? sendDate; | String? sendDate; | ||||
| this.message, | this.message, | ||||
| this.tbCropId, | this.tbCropId, | ||||
| this.tbEntityId, | this.tbEntityId, | ||||
| this.externalId, | |||||
| this.contents, | this.contents, | ||||
| this.createdDate, | this.createdDate, | ||||
| this.sendDate, | this.sendDate, | ||||
| this.contents = noti.contents; | this.contents = noti.contents; | ||||
| this.tbCropId = noti.tbCropId; | this.tbCropId = noti.tbCropId; | ||||
| this.tbEntityId = noti.tbEntityId; | this.tbEntityId = noti.tbEntityId; | ||||
| this.externalId = noti.externalId; | |||||
| this.subject = noti.subject; | this.subject = noti.subject; | ||||
| this.message = noti.message; | this.message = noti.message; | ||||
| this.createdDate = noti.createdDate; | this.createdDate = noti.createdDate; | ||||
| message = json['message']; | message = json['message']; | ||||
| tbCropId = json['tbCropId']; | tbCropId = json['tbCropId']; | ||||
| tbEntityId = json['tbEntityId']; | tbEntityId = json['tbEntityId']; | ||||
| externalId = json['externalId']; | |||||
| contents = json['contents']; | contents = json['contents']; | ||||
| createdDate = json['createdDate']; | createdDate = json['createdDate']; | ||||
| sendDate = json['sendDate']; | sendDate = json['sendDate']; | ||||
| data['message'] = this.message; | data['message'] = this.message; | ||||
| data['tbCropId'] = this.tbCropId; | data['tbCropId'] = this.tbCropId; | ||||
| data['tbEntityId'] = this.tbEntityId; | data['tbEntityId'] = this.tbEntityId; | ||||
| data['externalId'] = this.externalId; | |||||
| data['contents'] = this.contents; | data['contents'] = this.contents; | ||||
| data['createdDate'] = this.createdDate; | data['createdDate'] = this.createdDate; | ||||
| data['sendDate'] = this.sendDate; | data['sendDate'] = this.sendDate; |
| import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart'; | import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/task/models/task_request.dart'; | import 'package:farm_tpf/presentation/screens/task/models/task_request.dart'; | ||||
| import 'package:farm_tpf/utils/const_common.dart'; | import 'package:farm_tpf/utils/const_common.dart'; | ||||
| import 'package:flutter/foundation.dart'; | |||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import '../../presentation/screens/codes/models/stamp_type.dart'; | import '../../presentation/screens/codes/models/stamp_type.dart'; | ||||
| import '../../presentation/screens/login/models/request_user.dart'; | import '../../presentation/screens/login/models/request_user.dart'; | ||||
| import '../../presentation/screens/login/models/response_user.dart'; | import '../../presentation/screens/login/models/response_user.dart'; | ||||
| import '../../presentation/screens/plot/models/area_filter.request.dart'; | |||||
| import '../../presentation/screens/task/models/task.dart'; | import '../../presentation/screens/task/models/task.dart'; | ||||
| import '../../presentation/screens/task/models/task_filter_request.dart'; | import '../../presentation/screens/task/models/task_filter_request.dart'; | ||||
| import '../../presentation/screens/task/models/task_update_request.dart'; | import '../../presentation/screens/task/models/task_update_request.dart'; | ||||
| required TaskFilterRequest filter, | required TaskFilterRequest filter, | ||||
| }) async { | }) async { | ||||
| try { | try { | ||||
| // var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size&sort=createdDate,${filter.sort ?? 'asc'}'; | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size'; | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size&sort=deadline,${filter.sort ?? 'asc'}'; | |||||
| var status = <bool>[]; | |||||
| if (filter.status != null) { | |||||
| status = filter.status!.map((e) { | |||||
| if (e == describeEnum(TaskStatus.completed)) { | |||||
| return true; | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| }).toList(); | |||||
| } | |||||
| var res = await dio.post(url, data: { | var res = await dio.post(url, data: { | ||||
| // 'status': filter.status, | |||||
| 'completed': status, | |||||
| "crop_id": filter.cropId, | "crop_id": filter.cropId, | ||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| //api/tb-entities/area | |||||
| Future<List<AreaFilter>> getAreasFilter() async { | |||||
| try { | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-entities/area'; | |||||
| var res = await dio.get( | |||||
| url, | |||||
| ); | |||||
| return (res.data as List).map((e) => AreaFilter.fromJson(e)).toList(); | |||||
| } catch (e) { | |||||
| rethrow; | |||||
| } | |||||
| } | |||||
| // Crop | // Crop | ||||
| Future<List<TbCropDTO>> crops({ | Future<List<TbCropDTO>> crops({ | ||||
| int page = 0, | int page = 0, | ||||
| required CropFilterRequest filter, | required CropFilterRequest filter, | ||||
| }) async { | }) async { | ||||
| try { | try { | ||||
| // var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size&sort=createdDate,${filter.sort ?? 'asc'}'; | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-crops/list?page=$page&size=$size'; | var url = '${ConstCommon.baseUrl}/api/tb-crops/list?page=$page&size=$size'; | ||||
| var res = await dio.post(url, data: { | var res = await dio.post(url, data: { | ||||
| 'tbSuppliesIds': filter.supplyIds, | 'tbSuppliesIds': filter.supplyIds, | ||||
| 'netHouseIds': filter.netHouseIds, | |||||
| 'code': filter.code, | |||||
| }); | }); | ||||
| return (res.data as List).map((e) => TbCropDTO.fromJson(e)).toList(); | return (res.data as List).map((e) => TbCropDTO.fromJson(e)).toList(); |
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||
| import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | |||||
| import 'package:get/get.dart'; | |||||
| import 'package:hive/hive.dart'; | import 'package:hive/hive.dart'; | ||||
| import 'package:path_provider/path_provider.dart'; | import 'package:path_provider/path_provider.dart'; | ||||
| import 'app.dart'; | import 'app.dart'; | ||||
| import 'presentation/screens/task/bloc/task_bloc.dart'; | import 'presentation/screens/task/bloc/task_bloc.dart'; | ||||
| final GlobalKey<NavigatorState> globalNavigator = GlobalKey<NavigatorState>(); | final GlobalKey<NavigatorState> globalNavigator = GlobalKey<NavigatorState>(); | ||||
| @pragma('vm:entry-point') | |||||
| void notificationTapBackground(NotificationResponse notificationResponse) { | |||||
| // handle action | |||||
| print('message from background: $notificationResponse'); | |||||
| } | |||||
| Future<void> main() async { | Future<void> main() async { | ||||
| WidgetsFlutterBinding.ensureInitialized(); | WidgetsFlutterBinding.ensureInitialized(); | ||||
| import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart'; | import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/notification/update_count_noti_bloc.dart'; | import 'package:farm_tpf/presentation/screens/notification/update_count_noti_bloc.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart'; | import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/task/task_detail_page.dart'; | |||||
| import 'package:farm_tpf/utils/NotificationsBloc.dart'; | import 'package:farm_tpf/utils/NotificationsBloc.dart'; | ||||
| import 'package:farm_tpf/utils/const_icons.dart'; | import 'package:farm_tpf/utils/const_icons.dart'; | ||||
| import 'package:farm_tpf/utils/pref.dart'; | import 'package:farm_tpf/utils/pref.dart'; | ||||
| onTap: () { | onTap: () { | ||||
| if (item.contents == "ENV_UPDATE") { | if (item.contents == "ENV_UPDATE") { | ||||
| Navigator.push( | Navigator.push( | ||||
| context, | |||||
| MaterialPageRoute( | |||||
| builder: (BuildContext context) => PlotDetailScreen( | |||||
| cropType: type, | |||||
| cropId: item.tbCropId ?? -1, | |||||
| initialIndex: 0, | |||||
| ))).then((value) { | |||||
| context, | |||||
| MaterialPageRoute( | |||||
| builder: (BuildContext context) => PlotDetailScreen( | |||||
| cropType: type, | |||||
| cropId: item.tbCropId ?? -1, | |||||
| initialIndex: 0, | |||||
| ), | |||||
| ), | |||||
| ).then((value) { | |||||
| if (item.isRead == 0) { | if (item.isRead == 0) { | ||||
| _updateReadNotification( | _updateReadNotification( | ||||
| context: context, | context: context, | ||||
| currentReachedMax: currentReachedMax); | currentReachedMax: currentReachedMax); | ||||
| } | } | ||||
| }); | }); | ||||
| } else if (item.contents == "TODO_LIST_CREATE" || item.contents == 'TODO_LIST_UPDATE') { | |||||
| Navigator.push( | |||||
| context, | |||||
| MaterialPageRoute( | |||||
| builder: (BuildContext context) => TaskDetailPage( | |||||
| taskId: item.externalId ?? -1, | |||||
| ), | |||||
| ), | |||||
| ).then((value) { | |||||
| if (item.isRead == 0) { | |||||
| _updateReadNotification( | |||||
| context: context, | |||||
| unread: unread, | |||||
| read: read, | |||||
| item: item, | |||||
| currentItems: currentItems, | |||||
| currentPage: currentPage, | |||||
| currentReachedMax: currentReachedMax); | |||||
| } | |||||
| }); | |||||
| } else {} | } else {} | ||||
| }), | }), | ||||
| Container(padding: EdgeInsets.only(left: 16, right: 16), child: DashLineWidget()) | Container(padding: EdgeInsets.only(left: 16, right: 16), child: DashLineWidget()) |
| import 'package:farm_tpf/custom_model/TbCropDTO.dart'; | import 'package:farm_tpf/custom_model/TbCropDTO.dart'; | ||||
| import 'package:farm_tpf/data/api/app_exception.dart'; | import 'package:farm_tpf/data/api/app_exception.dart'; | ||||
| import 'package:farm_tpf/data/repository/repository.dart'; | import 'package:farm_tpf/data/repository/repository.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/plot/models/area_filter.request.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/plot/models/crop_filter_request.dart'; | import 'package:farm_tpf/presentation/screens/plot/models/crop_filter_request.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart'; | import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| PlotBloc({required this.repository}) : super(PlotInitial()); | PlotBloc({required this.repository}) : super(PlotInitial()); | ||||
| static int pageSize = 20; | static int pageSize = 20; | ||||
| final searchCtl = TextEditingController(); | |||||
| var supplyRaws = <SupplyFilter>[]; | var supplyRaws = <SupplyFilter>[]; | ||||
| var supplies = ValueNotifier(<ItemDropDown>[]); | var supplies = ValueNotifier(<ItemDropDown>[]); | ||||
| var selectedSupply = ValueNotifier(<ItemDropDown>[]); | var selectedSupply = ValueNotifier(<ItemDropDown>[]); | ||||
| var areaRaws = <AreaFilter>[]; | |||||
| var areas = ValueNotifier(<ItemDropDown>[]); | |||||
| var selectedArea = ValueNotifier(<ItemDropDown>[]); | |||||
| @override | @override | ||||
| Stream<PlotState> mapEventToState( | Stream<PlotState> mapEventToState( | ||||
| PlotEvent event, | PlotEvent event, | ||||
| ) | ) | ||||
| .toList() | .toList() | ||||
| : <int>[]; | : <int>[]; | ||||
| var filter = CropFilterRequest()..supplyIds = supplyIds; | |||||
| var areaIds = selectedArea.value.length > 0 | |||||
| ? selectedArea.value | |||||
| .map( | |||||
| (e) => int.tryParse(e.key ?? '') ?? -1, | |||||
| ) | |||||
| .toList() | |||||
| : <int>[]; | |||||
| var filter = CropFilterRequest() | |||||
| ..supplyIds = supplyIds | |||||
| ..netHouseIds = areaIds | |||||
| ..code = searchCtl.text; | |||||
| return await repository.crops(page: 0, filter: filter); | return await repository.crops(page: 0, filter: filter); | ||||
| } | } | ||||
| (e) => ItemDropDown(key: e.id?.toString(), value: e.name), | (e) => ItemDropDown(key: e.id?.toString(), value: e.name), | ||||
| ) | ) | ||||
| .toList(); | .toList(); | ||||
| areaRaws = await repository.getAreasFilter(); | |||||
| areas.value = areaRaws | |||||
| .map( | |||||
| (e) => ItemDropDown(key: e.id?.toString(), value: e.name), | |||||
| ) | |||||
| .toList(); | |||||
| // emit(CreateStampPrepareDataSuccessful()); | // emit(CreateStampPrepareDataSuccessful()); | ||||
| } catch (e) { | } catch (e) { | ||||
| print(e); | print(e); |
| class AreaFilter { | |||||
| int? id; | |||||
| String? name; | |||||
| AreaFilter({ | |||||
| this.id, | |||||
| this.name, | |||||
| }); | |||||
| AreaFilter.fromJson(Map<String, dynamic> json) { | |||||
| id = json['id']; | |||||
| name = json['name']; | |||||
| } | |||||
| Map<String, dynamic> toJson() { | |||||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
| data['id'] = this.id; | |||||
| data['name'] = this.name; | |||||
| return data; | |||||
| } | |||||
| } |
| class CropFilterRequest { | class CropFilterRequest { | ||||
| List<int>? supplyIds; | List<int>? supplyIds; | ||||
| List<int>? netHouseIds; | |||||
| String? sort; | String? sort; | ||||
| String? code; | |||||
| CropFilterRequest({this.supplyIds, this.sort}); | CropFilterRequest({this.supplyIds, this.sort}); | ||||
| CropFilterRequest.fromJson(Map<String, dynamic> json) { | CropFilterRequest.fromJson(Map<String, dynamic> json) { | ||||
| supplyIds = json['tbSuppliesIds'].cast<String>(); | supplyIds = json['tbSuppliesIds'].cast<String>(); | ||||
| netHouseIds = json['netHouseIds'].cast<String>(); | |||||
| sort = json['sort']; | sort = json['sort']; | ||||
| code = json['code']; | |||||
| } | } | ||||
| Map<String, dynamic> toJson() { | Map<String, dynamic> toJson() { | ||||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
| data['tbSuppliesIds'] = this.supplyIds; | data['tbSuppliesIds'] = this.supplyIds; | ||||
| data['netHouseIds'] = this.netHouseIds; | |||||
| data['sort'] = this.sort; | data['sort'] = this.sort; | ||||
| data['code'] = this.code; | |||||
| return data; | return data; | ||||
| } | } | ||||
| } | } |
| ), | ), | ||||
| ), | ), | ||||
| WidgetSearch( | WidgetSearch( | ||||
| searchController: TextEditingController(), | |||||
| searchController: bloc.searchCtl, | |||||
| onPressed: (value) { | onPressed: (value) { | ||||
| FocusScope.of(context).requestFocus(FocusNode()); | FocusScope.of(context).requestFocus(FocusNode()); | ||||
| BlocProvider.of<PlotBloc>(context).add(OnSearch(searchString: value)); | |||||
| bloc.add(OnRefresh()); | |||||
| }, | }, | ||||
| ), | ), | ||||
| ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.selectedSupply, | |||||
| builder: (context, selecteds, _) { | |||||
| return ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.supplies, | |||||
| builder: (context, status, _) { | |||||
| return MultipleSelectBottomSheet( | |||||
| dataSources: status, | |||||
| initValue: selecteds, | |||||
| onSelected: (val) { | |||||
| bloc.selectedSupply.value = val; | |||||
| Helpers.hideKeyboard(context); | |||||
| bloc.add(OnRefresh()); | |||||
| Row( | |||||
| children: [ | |||||
| ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.selectedSupply, | |||||
| builder: (context, selecteds, _) { | |||||
| return ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.supplies, | |||||
| builder: (context, status, _) { | |||||
| return MultipleSelectBottomSheet( | |||||
| dataSources: status, | |||||
| initValue: selecteds, | |||||
| onSelected: (val) { | |||||
| bloc.selectedSupply.value = val; | |||||
| Helpers.hideKeyboard(context); | |||||
| bloc.add(OnRefresh()); | |||||
| }, | |||||
| hint: 'Giống', | |||||
| ); | |||||
| }, | }, | ||||
| hint: 'Giống', | |||||
| ); | ); | ||||
| }, | }, | ||||
| ); | |||||
| }, | |||||
| ), | |||||
| ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.selectedArea, | |||||
| builder: (context, selecteds, _) { | |||||
| return ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.areas, | |||||
| builder: (context, status, _) { | |||||
| return MultipleSelectBottomSheet( | |||||
| dataSources: status, | |||||
| initValue: selecteds, | |||||
| onSelected: (val) { | |||||
| bloc.selectedArea.value = val; | |||||
| Helpers.hideKeyboard(context); | |||||
| bloc.add(OnRefresh()); | |||||
| }, | |||||
| hint: 'Khu vực', | |||||
| ); | |||||
| }, | |||||
| ); | |||||
| }, | |||||
| ), | |||||
| ], | |||||
| ), | ), | ||||
| Expanded( | Expanded( | ||||
| child: BlocBuilder<PlotBloc, PlotState>( | child: BlocBuilder<PlotBloc, PlotState>( |
| final Repository repository; | final Repository repository; | ||||
| int pageSize = 20; | int pageSize = 20; | ||||
| TaskBloc(this.repository) : super(TaskInitial()); | TaskBloc(this.repository) : super(TaskInitial()); | ||||
| bool isFetching = false; // Add this flag | |||||
| var status = ValueNotifier( | var status = ValueNotifier( | ||||
| TaskStatus.values | TaskStatus.values | ||||
| .map( | .map( | ||||
| Stream<TaskState> mapEventToState( | Stream<TaskState> mapEventToState( | ||||
| TaskEvent event, | TaskEvent event, | ||||
| ) async* { | ) async* { | ||||
| if (event is DataFetched && !(state is TaskSuccess && ((state as TaskSuccess).hasReachedMax ?? false))) { | |||||
| try { | |||||
| if (state is TaskInitial) { | |||||
| yield (TaskLoading()); | |||||
| final response = await getListTask(0); | |||||
| yield TaskSuccess( | |||||
| items: response, | |||||
| page: 0, | |||||
| hasReachedMax: response.length < pageSize ? true : false, | |||||
| ); | |||||
| } | |||||
| if (state is TaskSuccess) { | |||||
| final currentState = state as TaskSuccess; | |||||
| if (currentState.hasReachedMax ?? false) { | |||||
| return; | |||||
| if (event is DataFetched) { | |||||
| if (state is TaskInitial || (state is TaskSuccess && (!((state as TaskSuccess).hasReachedMax ?? false)))) { | |||||
| try { | |||||
| final currentState = state; | |||||
| int nextPage = 0; | |||||
| if (currentState is TaskSuccess) { | |||||
| nextPage = ((currentState.items?.length ?? 0) / 20).floor(); | |||||
| } | } | ||||
| int page = (currentState.page ?? 0) + 1; | |||||
| final response = await getListTask(page); | |||||
| isFetching = true; | |||||
| final response = await getListTask(nextPage); | |||||
| final hasReachedMax = response.length < pageSize; | |||||
| isFetching = false; | |||||
| yield response.isEmpty | yield response.isEmpty | ||||
| ? currentState.copyWith(hasReachedMax: true) | |||||
| : TaskSuccess( | |||||
| items: (currentState.items ?? []) + response, | |||||
| page: (currentState.page ?? 0) + 1, | |||||
| hasReachedMax: false, | |||||
| ); | |||||
| ? (currentState is TaskSuccess ? currentState.copyWith(hasReachedMax: true) : TaskSuccess(items: [], hasReachedMax: true)) | |||||
| : (currentState is TaskSuccess | |||||
| ? TaskSuccess(items: (currentState.items ?? []) + response, hasReachedMax: hasReachedMax) | |||||
| : TaskSuccess(items: response, hasReachedMax: hasReachedMax)); | |||||
| } catch (e) { | |||||
| isFetching = false; | |||||
| var errorString = AppException.handleError(e); | |||||
| yield (TaskFailure(errorString: errorString)); | |||||
| } | } | ||||
| } catch (e) { | |||||
| var errorString = AppException.handleError(e); | |||||
| yield (TaskFailure(errorString: errorString)); | |||||
| } | } | ||||
| } | } | ||||
| // if (event is DataFetched && !(state is TaskSuccess && ((state as TaskSuccess).hasReachedMax ?? false))) { | |||||
| // try { | |||||
| // if (state is TaskInitial) { | |||||
| // yield (TaskLoading()); | |||||
| // final response = await getListTask(0); | |||||
| // yield TaskSuccess( | |||||
| // items: response, | |||||
| // page: 0, | |||||
| // hasReachedMax: response.length < pageSize ? true : false, | |||||
| // ); | |||||
| // } | |||||
| // if (state is TaskSuccess) { | |||||
| // final currentState = state as TaskSuccess; | |||||
| // // if (currentState.hasReachedMax ?? false) { | |||||
| // // return; | |||||
| // // } | |||||
| // int page = (currentState.page ?? 0) + 1; | |||||
| // final response = await getListTask(page); | |||||
| // yield response.isEmpty | |||||
| // ? currentState.copyWith(hasReachedMax: true) | |||||
| // : TaskSuccess( | |||||
| // items: (currentState.items ?? []) + response, | |||||
| // page: (currentState.page ?? 0) + 1, | |||||
| // hasReachedMax: false, | |||||
| // ); | |||||
| // } | |||||
| // } catch (e) { | |||||
| // var errorString = AppException.handleError(e); | |||||
| // yield (TaskFailure(errorString: errorString)); | |||||
| // } | |||||
| // } | |||||
| if (event is OnRefresh) { | if (event is OnRefresh) { | ||||
| try { | try { | ||||
| isFetching = true; | |||||
| yield (TaskLoading()); | yield (TaskLoading()); | ||||
| final response = await getListTask(0); | final response = await getListTask(0); | ||||
| isFetching = false; | |||||
| var items = <Task>[]; | var items = <Task>[]; | ||||
| response.forEach((element) { | response.forEach((element) { | ||||
| items.add(Task.clone(element)); | items.add(Task.clone(element)); | ||||
| hasReachedMax: items.length < pageSize ? true : false, | hasReachedMax: items.length < pageSize ? true : false, | ||||
| ); | ); | ||||
| } catch (e) { | } catch (e) { | ||||
| isFetching = false; | |||||
| yield (TaskFailure(errorString: AppException.handleError(e))); | yield (TaskFailure(errorString: AppException.handleError(e))); | ||||
| } | } | ||||
| } else if (event is OnSearch) { | } else if (event is OnSearch) { | ||||
| try { | try { | ||||
| isFetching = true; | |||||
| yield (TaskLoading()); | yield (TaskLoading()); | ||||
| final response = await getListTask(0); | final response = await getListTask(0); | ||||
| isFetching = false; | |||||
| yield TaskSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false); | yield TaskSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false); | ||||
| } catch (e) { | } catch (e) { | ||||
| yield (TaskFailure(errorString: AppException.handleError(e))); | yield (TaskFailure(errorString: AppException.handleError(e))); | ||||
| ..cropId = cropId | ..cropId = cropId | ||||
| ..sort = sort.value | ..sort = sort.value | ||||
| ..status = selectedStatus.value.map((e) => e.key ?? '').toList(); | ..status = selectedStatus.value.map((e) => e.key ?? '').toList(); | ||||
| return await repository.tasks(page: 0, filter: filter); | |||||
| return await repository.tasks(page: page, filter: filter); | |||||
| } | } | ||||
| Future<void> updateStatusTask( | Future<void> updateStatusTask( |
| bloc.add(DataFetched()); | bloc.add(DataFetched()); | ||||
| _scrollController.addListener(() { | _scrollController.addListener(() { | ||||
| if (bloc.isFetching) return; | |||||
| final maxScroll = _scrollController.position.maxScrollExtent; | final maxScroll = _scrollController.position.maxScrollExtent; | ||||
| final currentScroll = _scrollController.position.pixels; | final currentScroll = _scrollController.position.pixels; | ||||
| if (maxScroll - currentScroll < _scrollThreshold) { | if (maxScroll - currentScroll < _scrollThreshold) { | ||||
| builder: (context, sort, _) { | builder: (context, sort, _) { | ||||
| return Button2Icon( | return Button2Icon( | ||||
| leftIcon: (sort == describeEnum(SortType.asc)) ? CupertinoIcons.arrow_up : CupertinoIcons.arrow_down, | leftIcon: (sort == describeEnum(SortType.asc)) ? CupertinoIcons.arrow_up : CupertinoIcons.arrow_down, | ||||
| title: 'Ngày tạo', | |||||
| title: 'Ngày hoàn thành', | |||||
| onPressed: () { | onPressed: () { | ||||
| if (sort == describeEnum(SortType.asc)) { | if (sort == describeEnum(SortType.asc)) { | ||||
| bloc.sort.value = describeEnum(SortType.desc); | bloc.sort.value = describeEnum(SortType.desc); | ||||
| ), | ), | ||||
| ], | ], | ||||
| ), | ), | ||||
| const SizedBox( | |||||
| height: 4, | |||||
| ), | |||||
| Expanded( | Expanded( | ||||
| child: mainBody(), | child: mainBody(), | ||||
| ), | ), | ||||
| child: ListView.builder( | child: ListView.builder( | ||||
| physics: AlwaysScrollableScrollPhysics(), | physics: AlwaysScrollableScrollPhysics(), | ||||
| itemBuilder: (BuildContext context, int index) { | itemBuilder: (BuildContext context, int index) { | ||||
| print('index: $index'); | |||||
| print('state.items: ${state.items?.length}'); | |||||
| return index >= (state.items ?? []).length | return index >= (state.items ?? []).length | ||||
| ? BottomLoader() | ? BottomLoader() | ||||
| : ItemTask( | : ItemTask( |
| import 'dart:convert'; | import 'dart:convert'; | ||||
| import 'package:farm_tpf/presentation/screens/task/task_detail_page.dart'; | |||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||
| import 'package:get/get.dart'; | import 'package:get/get.dart'; | ||||
| import '../presentation/screens/plot_detail/sc_plot_detail.dart'; | |||||
| import '../utils/pref.dart'; | import '../utils/pref.dart'; | ||||
| import 'package:firebase_messaging/firebase_messaging.dart'; | import 'package:firebase_messaging/firebase_messaging.dart'; | ||||
| import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | ||||
| FirebaseMessaging.onMessage.listen( | FirebaseMessaging.onMessage.listen( | ||||
| (RemoteMessage message) { | (RemoteMessage message) { | ||||
| print('Got a message whilst in the foreground!'); | print('Got a message whilst in the foreground!'); | ||||
| print('Message data: $message'); | |||||
| print('Message data: ${messaging.toString()}'); | |||||
| // increase count unread notification | // increase count unread notification | ||||
| // countNotificationUnRead.value = countNotificationUnRead.value + 1; | // countNotificationUnRead.value = countNotificationUnRead.value + 1; | ||||
| android: androidDetails, | android: androidDetails, | ||||
| ); | ); | ||||
| var dataPayload = json.encode(message.data); | |||||
| try { | try { | ||||
| var dataPayload = json.encode(message.data); | |||||
| // var entityType = message.data['entity_type']; | // var entityType = message.data['entity_type']; | ||||
| // var entityData = message.data['entity_data']; | // var entityData = message.data['entity_data']; | ||||
| // var systemMessage = message.data['system_message']; | // var systemMessage = message.data['system_message']; | ||||
| }, | }, | ||||
| ); | ); | ||||
| @pragma('vm:entry-point') | |||||
| void notificationTapBackground(NotificationResponse notificationResponse) { | |||||
| // handle action | |||||
| print('message from background: $notificationResponse'); | |||||
| } | |||||
| //Interaction Message from background | //Interaction Message from background | ||||
| FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { | FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { | ||||
| print('message from background: ${message}'); | print('message from background: ${message}'); | ||||
| static Future onDidReceiveLocalNotification(int? id, String? title, String? body, String? payload) async { | static Future onDidReceiveLocalNotification(int? id, String? title, String? body, String? payload) async { | ||||
| // display a dialog with the notification details, tap ok to go to another page | // display a dialog with the notification details, tap ok to go to another page | ||||
| print('handle touch on foreground'); | |||||
| } | } | ||||
| static Future selectNotification(String? payload) async { | static Future selectNotification(String? payload) async { | ||||
| } | } | ||||
| static void handleNavigateScreen(dynamic data) { | static void handleNavigateScreen(dynamic data) { | ||||
| print(data); | |||||
| try { | |||||
| if (data['contents'] == 'TODO_LIST_CREATE' || data['contents'] == 'TODO_LIST_UPDATE') { | |||||
| Get.to(() => TaskDetailPage(taskId: int.tryParse(data['externalId']) ?? -1)); | |||||
| } else if (data['contents'] == 'ENV_UPDATE') { | |||||
| Get.to( | |||||
| () => PlotDetailScreen( | |||||
| cropType: int.tryParse(data['tbCropType']) ?? -1, | |||||
| cropId: int.tryParse(data['tbCropId']) ?? -1, | |||||
| initialIndex: 0, | |||||
| ), | |||||
| ); | |||||
| } else if (data['contents'] == 'PIC_UPDATE') { | |||||
| Get.to( | |||||
| () => PlotDetailScreen( | |||||
| cropType: int.tryParse(data['tbCropType']) ?? -1, | |||||
| cropId: int.tryParse(data['tbCropId']) ?? -1, | |||||
| initialIndex: 1, | |||||
| ), | |||||
| ); | |||||
| } else { | |||||
| print(data['contents']); | |||||
| } | |||||
| print(data); | |||||
| } catch (e) { | |||||
| print(e); | |||||
| } | |||||
| } | } | ||||
| } | |||||
| Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { | |||||
| print('Handling a background message: ${message}'); | |||||
| static Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { | |||||
| print('Handling a background message: ${message}'); | |||||
| _handleMessage(message); | |||||
| } | |||||
| } | } |