mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
made communities paginatable.
This commit is contained in:
@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_management_body.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/communities_pagination_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
|
||||
@ -46,37 +46,20 @@ class SpaceManagementPage extends StatelessWidget {
|
||||
|
||||
class _FakeCommunitiesService extends CommunitiesService {
|
||||
@override
|
||||
Future<List<CommunityModel>> getCommunity(LoadCommunitiesParam param) async {
|
||||
return Future.delayed(
|
||||
const Duration(seconds: 1),
|
||||
() => [
|
||||
const CommunityModel(
|
||||
Future<CommunitiesPaginationModel> getCommunity(LoadCommunitiesParam param) {
|
||||
return Future.value(const CommunitiesPaginationModel(
|
||||
communities: [
|
||||
CommunityModel(
|
||||
uuid: '1',
|
||||
name: 'Community 1',
|
||||
spaces: [
|
||||
SpaceModel(
|
||||
uuid: '3',
|
||||
spaceName: 'Space 1',
|
||||
icon: 'assets/icons/space.png',
|
||||
children: [
|
||||
SpaceModel(
|
||||
uuid: '4',
|
||||
spaceName: 'Space 2',
|
||||
icon: 'assets/icons/space.png',
|
||||
children: [],
|
||||
status: SpaceStatus.active,
|
||||
),
|
||||
],
|
||||
status: SpaceStatus.active,
|
||||
),
|
||||
],
|
||||
),
|
||||
const CommunityModel(
|
||||
uuid: '2',
|
||||
name: 'Community 1',
|
||||
spaces: [],
|
||||
),
|
||||
],
|
||||
);
|
||||
page: 1,
|
||||
size: 10,
|
||||
hasNext: false,
|
||||
totalItems: 2,
|
||||
totalPages: 1,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/communities_pagination_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart';
|
||||
import 'package:syncrow_web/services/api/api_exception.dart';
|
||||
@ -15,28 +15,25 @@ class RemoteCommunitiesService implements CommunitiesService {
|
||||
static const _defaultErrorMessage = 'Failed to load communities';
|
||||
|
||||
@override
|
||||
Future<List<CommunityModel>> getCommunity(LoadCommunitiesParam param) async {
|
||||
Future<CommunitiesPaginationModel> getCommunity(LoadCommunitiesParam param) async {
|
||||
final projectUuid = await ProjectManager.getProjectUUID();
|
||||
if (projectUuid == null) throw APIException('Project UUID is not set');
|
||||
|
||||
try {
|
||||
final allCommunities = <CommunityModel>[];
|
||||
await _httpService.get(
|
||||
final response = await _httpService.get(
|
||||
path: await _makeUrl(),
|
||||
queryParameters: {
|
||||
'page': param.page,
|
||||
'size': param.size,
|
||||
'includeSpaces': param.includeSpaces,
|
||||
if (param.search.isNotEmpty) 'search': param.search,
|
||||
},
|
||||
expectedResponseModel: (json) {
|
||||
final response = json as Map<String, dynamic>;
|
||||
final jsonData = response['data'] as List<dynamic>? ?? [];
|
||||
return jsonData
|
||||
.map(
|
||||
(jsonItem) => CommunityModel.fromJson(
|
||||
jsonItem as Map<String, dynamic>,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return CommunitiesPaginationModel.fromJson(json as Map<String, dynamic>);
|
||||
},
|
||||
);
|
||||
|
||||
return allCommunities;
|
||||
return response;
|
||||
} on DioException catch (e) {
|
||||
final message = e.response?.data as Map<String, dynamic>?;
|
||||
final error = message?['error'] as Map<String, dynamic>?;
|
||||
|
@ -0,0 +1,69 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
||||
|
||||
class CommunitiesPaginationModel extends Equatable {
|
||||
const CommunitiesPaginationModel({
|
||||
required this.communities,
|
||||
required this.page,
|
||||
required this.size,
|
||||
required this.hasNext,
|
||||
required this.totalItems,
|
||||
required this.totalPages,
|
||||
});
|
||||
|
||||
final List<CommunityModel> communities;
|
||||
final int page;
|
||||
final int size;
|
||||
final bool hasNext;
|
||||
final int totalItems;
|
||||
final int totalPages;
|
||||
|
||||
const CommunitiesPaginationModel.empty()
|
||||
: communities = const [],
|
||||
page = 1,
|
||||
size = 25,
|
||||
hasNext = false,
|
||||
totalItems = 0,
|
||||
totalPages = 0;
|
||||
|
||||
factory CommunitiesPaginationModel.fromJson(Map<String, dynamic> json) {
|
||||
return CommunitiesPaginationModel(
|
||||
communities: (json['data'] as List<dynamic>? ?? [])
|
||||
.map((e) => CommunityModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
page: json['page'] as int? ?? 1,
|
||||
size: json['size'] as int? ?? 25,
|
||||
hasNext: json['hasNext'] as bool? ?? false,
|
||||
totalItems: json['totalItems'] as int? ?? 0,
|
||||
totalPages: json['totalPages'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
CommunitiesPaginationModel copyWith({
|
||||
List<CommunityModel>? communities,
|
||||
int? page,
|
||||
int? size,
|
||||
bool? hasNext,
|
||||
int? totalItems,
|
||||
int? totalPages,
|
||||
}) {
|
||||
return CommunitiesPaginationModel(
|
||||
communities: communities ?? this.communities,
|
||||
page: page ?? this.page,
|
||||
size: size ?? this.size,
|
||||
hasNext: hasNext ?? this.hasNext,
|
||||
totalItems: totalItems ?? this.totalItems,
|
||||
totalPages: totalPages ?? this.totalPages,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
communities,
|
||||
page,
|
||||
size,
|
||||
hasNext,
|
||||
totalItems,
|
||||
totalPages,
|
||||
];
|
||||
}
|
@ -1,3 +1,32 @@
|
||||
class LoadCommunitiesParam {
|
||||
const LoadCommunitiesParam();
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class LoadCommunitiesParam extends Equatable {
|
||||
const LoadCommunitiesParam({
|
||||
this.page = 1,
|
||||
this.size = 25,
|
||||
this.search = '',
|
||||
this.includeSpaces = true,
|
||||
});
|
||||
|
||||
final int page;
|
||||
final int size;
|
||||
final String search;
|
||||
final bool includeSpaces;
|
||||
|
||||
LoadCommunitiesParam copyWith({
|
||||
int? page,
|
||||
int? size,
|
||||
String? search,
|
||||
bool? includeSpaces,
|
||||
}) {
|
||||
return LoadCommunitiesParam(
|
||||
page: page ?? this.page,
|
||||
size: size ?? this.size,
|
||||
search: search ?? this.search,
|
||||
includeSpaces: includeSpaces ?? this.includeSpaces,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, search, includeSpaces];
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/communities_pagination_model.dart';
|
||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||
|
||||
abstract class CommunitiesService {
|
||||
Future<List<CommunityModel>> getCommunity(LoadCommunitiesParam param);
|
||||
Future<CommunitiesPaginationModel> getCommunity(LoadCommunitiesParam param);
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ class CommunitiesBloc extends Bloc<CommunitiesEvent, CommunitiesState> {
|
||||
}) : _communitiesService = communitiesService,
|
||||
super(const CommunitiesState()) {
|
||||
on<LoadCommunities>(_onLoadCommunities);
|
||||
on<LoadMoreCommunities>(_onLoadMoreCommunities);
|
||||
on<SearchCommunities>(_onSearchCommunities);
|
||||
}
|
||||
|
||||
final CommunitiesService _communitiesService;
|
||||
@ -23,24 +25,113 @@ class CommunitiesBloc extends Bloc<CommunitiesEvent, CommunitiesState> {
|
||||
Emitter<CommunitiesState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CommunitiesState(status: CommunitiesStatus.loading));
|
||||
final communities = await _communitiesService.getCommunity(event.param);
|
||||
emit(state.copyWith(status: CommunitiesStatus.loading));
|
||||
|
||||
final paginationResponse = await _communitiesService.getCommunity(event.param);
|
||||
|
||||
emit(
|
||||
CommunitiesState(
|
||||
status: CommunitiesStatus.success,
|
||||
communities: communities,
|
||||
communities: paginationResponse.communities,
|
||||
hasNext: paginationResponse.hasNext,
|
||||
currentPage: paginationResponse.page,
|
||||
searchQuery: event.param.search,
|
||||
),
|
||||
);
|
||||
} on APIException catch (e) {
|
||||
emit(
|
||||
CommunitiesState(
|
||||
state.copyWith(
|
||||
status: CommunitiesStatus.failure,
|
||||
errorMessage: e.message,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: CommunitiesStatus.failure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadMoreCommunities(
|
||||
LoadMoreCommunities event,
|
||||
Emitter<CommunitiesState> emit,
|
||||
) async {
|
||||
if (!state.hasNext || state.isLoadingMore) return;
|
||||
|
||||
try {
|
||||
emit(state.copyWith(isLoadingMore: true));
|
||||
|
||||
final param = LoadCommunitiesParam(
|
||||
page: state.currentPage + 1,
|
||||
search: state.searchQuery,
|
||||
);
|
||||
|
||||
final paginationResponse = await _communitiesService.getCommunity(param);
|
||||
|
||||
final updatedCommunities = List<CommunityModel>.from(state.communities)
|
||||
..addAll(paginationResponse.communities);
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
communities: updatedCommunities,
|
||||
hasNext: paginationResponse.hasNext,
|
||||
currentPage: paginationResponse.page,
|
||||
isLoadingMore: false,
|
||||
),
|
||||
);
|
||||
} on APIException catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
isLoadingMore: false,
|
||||
errorMessage: e.message,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
isLoadingMore: false,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSearchCommunities(
|
||||
SearchCommunities event,
|
||||
Emitter<CommunitiesState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(state.copyWith(status: CommunitiesStatus.loading));
|
||||
|
||||
final param = LoadCommunitiesParam(
|
||||
page: 1,
|
||||
search: event.searchQuery,
|
||||
);
|
||||
|
||||
final paginationResponse = await _communitiesService.getCommunity(param);
|
||||
|
||||
emit(
|
||||
CommunitiesState(
|
||||
status: CommunitiesStatus.success,
|
||||
communities: paginationResponse.communities,
|
||||
hasNext: paginationResponse.hasNext,
|
||||
currentPage: paginationResponse.page,
|
||||
searchQuery: event.searchQuery,
|
||||
),
|
||||
);
|
||||
} on APIException catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: CommunitiesStatus.failure,
|
||||
errorMessage: e.message,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: CommunitiesStatus.failure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
|
@ -15,3 +15,19 @@ class LoadCommunities extends CommunitiesEvent {
|
||||
@override
|
||||
List<Object?> get props => [param];
|
||||
}
|
||||
|
||||
class LoadMoreCommunities extends CommunitiesEvent {
|
||||
const LoadMoreCommunities();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class SearchCommunities extends CommunitiesEvent {
|
||||
const SearchCommunities(this.searchQuery);
|
||||
|
||||
final String searchQuery;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [searchQuery];
|
||||
}
|
||||
|
@ -7,12 +7,48 @@ final class CommunitiesState extends Equatable {
|
||||
this.status = CommunitiesStatus.initial,
|
||||
this.communities = const [],
|
||||
this.errorMessage,
|
||||
this.isLoadingMore = false,
|
||||
this.hasNext = false,
|
||||
this.currentPage = 1,
|
||||
this.searchQuery = '',
|
||||
});
|
||||
|
||||
final CommunitiesStatus status;
|
||||
final List<CommunityModel> communities;
|
||||
final String? errorMessage;
|
||||
final bool isLoadingMore;
|
||||
final bool hasNext;
|
||||
final int currentPage;
|
||||
final String searchQuery;
|
||||
|
||||
CommunitiesState copyWith({
|
||||
CommunitiesStatus? status,
|
||||
List<CommunityModel>? communities,
|
||||
String? errorMessage,
|
||||
bool? isLoadingMore,
|
||||
bool? hasNext,
|
||||
int? currentPage,
|
||||
String? searchQuery,
|
||||
}) {
|
||||
return CommunitiesState(
|
||||
status: status ?? this.status,
|
||||
communities: communities ?? this.communities,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||
hasNext: hasNext ?? this.hasNext,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
searchQuery: searchQuery ?? this.searchQuery,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, communities, errorMessage];
|
||||
List<Object?> get props => [
|
||||
status,
|
||||
communities,
|
||||
errorMessage,
|
||||
isLoadingMore,
|
||||
hasNext,
|
||||
currentPage,
|
||||
searchQuery,
|
||||
];
|
||||
}
|
||||
|
Reference in New Issue
Block a user