Added pagination and search logic in space tree

This commit is contained in:
Abdullah Alassaf
2025-04-06 01:14:16 +03:00
parent 77a9aa2f19
commit ab3f268f29
9 changed files with 284 additions and 140 deletions

View File

@ -34,9 +34,8 @@ class CommunityDropdown extends StatelessWidget {
const SizedBox(height: 8), const SizedBox(height: 8),
BlocBuilder<SpaceTreeBloc, SpaceTreeState>( BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
builder: (context, state) { builder: (context, state) {
List<CommunityModel> communities = state.isSearching List<CommunityModel> communities =
? state.filteredCommunity state.searchQuery.isNotEmpty ? state.filteredCommunity : state.communityList;
: state.communityList;
return SizedBox( return SizedBox(
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(

View File

@ -1,7 +1,10 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/space_tree/model/pagination_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart';
@ -18,7 +21,10 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
on<ClearCachedData>(_clearCachedData); on<ClearCachedData>(_clearCachedData);
on<OnCommunityAdded>(_onCommunityAdded); on<OnCommunityAdded>(_onCommunityAdded);
on<OnCommunityUpdated>(_onCommunityUpdate); on<OnCommunityUpdated>(_onCommunityUpdate);
on<PaginationEvent>(_fetchPaginationSpaces);
on<DebouncedSearchEvent>(_onDebouncedSearch);
} }
Timer _timer = Timer(const Duration(microseconds: 0), () {});
void _onCommunityUpdate( void _onCommunityUpdate(
OnCommunityUpdated event, OnCommunityUpdated event,
@ -37,7 +43,7 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
updatedCommunities[index] = updatedCommunity; updatedCommunities[index] = updatedCommunity;
emit(state.copyWith(communitiesList: updatedCommunities)); emit(state.copyWith(communitiesList: updatedCommunities));
} else { } else {
emit(SpaceTreeErrorState('Community not found in the list.')); emit(const SpaceTreeErrorState('Community not found in the list.'));
} }
} catch (e) { } catch (e) {
emit(SpaceTreeErrorState('Error updating community: $e')); emit(SpaceTreeErrorState('Error updating community: $e'));
@ -49,8 +55,8 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
try { try {
final projectUuid = await ProjectManager.getProjectUUID() ?? ''; final projectUuid = await ProjectManager.getProjectUUID() ?? '';
List<CommunityModel> communities = PaginationModel paginationModel = await CommunitySpaceManagementApi()
await CommunitySpaceManagementApi().fetchCommunities(projectUuid, includeSpaces: true); .fetchCommunitiesAndSpaces(projectId: projectUuid, page: 1);
// List<CommunityModel> updatedCommunities = await Future.wait( // List<CommunityModel> updatedCommunities = await Future.wait(
// communities.map((community) async { // communities.map((community) async {
@ -69,12 +75,38 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
// }).toList(), // }).toList(),
// ); // );
emit(state.copyWith(communitiesList: communities, expandedCommunity: [], expandedSpaces: [])); emit(state.copyWith(
communitiesList: paginationModel.communities,
expandedCommunity: [],
expandedSpaces: [],
paginationModel: paginationModel));
} catch (e) { } catch (e) {
emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
} }
} }
_fetchPaginationSpaces(PaginationEvent event, Emitter<SpaceTreeState> emit) async {
emit(state.copyWith(paginationIsLoading: true));
PaginationModel paginationModel = event.paginationModel;
List<CommunityModel> communities = List<CommunityModel>.from(event.communities);
try {
if (paginationModel.hasNext && state.searchQuery.isEmpty) {
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
paginationModel = await CommunitySpaceManagementApi().fetchCommunitiesAndSpaces(
projectId: projectUuid, page: paginationModel.pageNum, search: state.searchQuery);
communities.addAll(paginationModel.communities);
}
} catch (e) {
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
}
emit(state.copyWith(
communitiesList: communities,
paginationModel: paginationModel,
paginationIsLoading: false));
}
void _onCommunityAdded(OnCommunityAdded event, Emitter<SpaceTreeState> emit) async { void _onCommunityAdded(OnCommunityAdded event, Emitter<SpaceTreeState> emit) async {
final updatedCommunities = List<CommunityModel>.from(state.communityList); final updatedCommunities = List<CommunityModel>.from(state.communityList);
updatedCommunities.add(event.newCommunity); updatedCommunities.add(event.newCommunity);
@ -264,28 +296,52 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
_onSearch(SearchQueryEvent event, Emitter<SpaceTreeState> emit) async { _onSearch(SearchQueryEvent event, Emitter<SpaceTreeState> emit) async {
try { try {
List<CommunityModel> communities = List.from(state.communityList); const duration = Duration(seconds: 1);
List<CommunityModel> filteredCommunity = []; if (_timer.isActive) {
_timer.cancel(); // clear timer
}
_timer = Timer(duration, () async => add(DebouncedSearchEvent(event.searchQuery)));
// List<CommunityModel> communities = List.from(state.communityList);
// List<CommunityModel> filteredCommunity = [];
// Filter communities and expand only those that match the query // Filter communities and expand only those that match the query
filteredCommunity = communities.where((community) { // filteredCommunity = communities.where((community) {
final containsQueryInCommunity = // final containsQueryInCommunity =
community.name.toLowerCase().contains(event.searchQuery.toLowerCase()); // community.name.toLowerCase().contains(event.searchQuery.toLowerCase());
final containsQueryInSpaces = // final containsQueryInSpaces =
community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase())); // community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase()));
return containsQueryInCommunity || containsQueryInSpaces; // return containsQueryInCommunity || containsQueryInSpaces;
}).toList(); // }).toList();
emit(state.copyWith( // emit(state.copyWith(
filteredCommunity: filteredCommunity, // filteredCommunity: filteredCommunity,
isSearching: event.searchQuery.isNotEmpty, // isSearching: event.searchQuery.isNotEmpty,
searchQuery: event.searchQuery)); // searchQuery: event.searchQuery));
} catch (e) { } catch (e) {
emit(const SpaceTreeErrorState('Something went wrong')); emit(const SpaceTreeErrorState('Something went wrong'));
} }
} }
_onDebouncedSearch(DebouncedSearchEvent event, Emitter<SpaceTreeState> emit) async {
emit(state.copyWith(
isSearching: true,
));
PaginationModel paginationModel = const PaginationModel.emptyConstructor();
try {
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
paginationModel = await CommunitySpaceManagementApi()
.fetchCommunitiesAndSpaces(projectId: projectUuid, page: 1, search: event.searchQuery);
} catch (_) {}
emit(state.copyWith(
filteredCommunity: paginationModel.communities,
isSearching: false,
searchQuery: event.searchQuery));
}
_clearAllData(ClearAllData event, Emitter<SpaceTreeState> emit) async { _clearAllData(ClearAllData event, Emitter<SpaceTreeState> emit) async {
try { try {
emit(state.copyWith( emit(state.copyWith(
@ -323,13 +379,13 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
} }
// Helper function to determine if any space or its children match the search query // Helper function to determine if any space or its children match the search query
bool _containsQuery(SpaceModel space, String query) { // bool _containsQuery(SpaceModel space, String query) {
final matchesSpace = space.name.toLowerCase().contains(query); // final matchesSpace = space.name.toLowerCase().contains(query);
final matchesChildren = // final matchesChildren =
space.children.any((child) => _containsQuery(child, query)); // Recursive check for children // space.children.any((child) => _containsQuery(child, query)); // Recursive check for children
return matchesSpace || matchesChildren; // return matchesSpace || matchesChildren;
} // }
List<String> _getAllChildIds(List<SpaceModel> spaces) { List<String> _getAllChildIds(List<SpaceModel> spaces) {
List<String> ids = []; List<String> ids = [];
@ -403,6 +459,7 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
@override @override
Future<void> close() async { Future<void> close() async {
_timer.cancel();
super.close(); super.close();
} }
} }

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/space_tree/model/pagination_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
@ -11,6 +12,16 @@ class SpaceTreeEvent extends Equatable {
class InitialEvent extends SpaceTreeEvent {} class InitialEvent extends SpaceTreeEvent {}
class PaginationEvent extends SpaceTreeEvent {
final PaginationModel paginationModel;
final List<CommunityModel> communities;
const PaginationEvent(this.paginationModel, this.communities);
@override
List<Object> get props => [paginationModel, communities];
}
class SearchForSpace extends SpaceTreeEvent { class SearchForSpace extends SpaceTreeEvent {
final String searchQuery; final String searchQuery;
@ -69,6 +80,15 @@ class SearchQueryEvent extends SpaceTreeEvent {
List<Object> get props => [searchQuery]; List<Object> get props => [searchQuery];
} }
class DebouncedSearchEvent extends SpaceTreeEvent {
final String searchQuery;
const DebouncedSearchEvent(this.searchQuery);
@override
List<Object> get props => [searchQuery];
}
class OnCommunityAdded extends SpaceTreeEvent { class OnCommunityAdded extends SpaceTreeEvent {
final CommunityModel newCommunity; final CommunityModel newCommunity;
const OnCommunityAdded(this.newCommunity); const OnCommunityAdded(this.newCommunity);
@ -85,7 +105,6 @@ class OnCommunityUpdated extends SpaceTreeEvent {
List<Object> get props => [updatedCommunity]; List<Object> get props => [updatedCommunity];
} }
class ClearAllData extends SpaceTreeEvent {} class ClearAllData extends SpaceTreeEvent {}
class ClearCachedData extends SpaceTreeEvent {} class ClearCachedData extends SpaceTreeEvent {}

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/space_tree/model/pagination_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class SpaceTreeState extends Equatable { class SpaceTreeState extends Equatable {
@ -12,6 +13,8 @@ class SpaceTreeState extends Equatable {
final List<String> soldCheck; final List<String> soldCheck;
final bool isSearching; final bool isSearching;
final String searchQuery; final String searchQuery;
final PaginationModel paginationModel;
final bool paginationIsLoading;
const SpaceTreeState( const SpaceTreeState(
{this.communityList = const [], {this.communityList = const [],
@ -23,7 +26,9 @@ class SpaceTreeState extends Equatable {
this.soldCheck = const [], this.soldCheck = const [],
this.isSearching = false, this.isSearching = false,
this.selectedCommunityAndSpaces = const {}, this.selectedCommunityAndSpaces = const {},
this.searchQuery = ''}); this.searchQuery = '',
this.paginationModel = const PaginationModel.emptyConstructor(),
this.paginationIsLoading = false});
SpaceTreeState copyWith( SpaceTreeState copyWith(
{List<CommunityModel>? communitiesList, {List<CommunityModel>? communitiesList,
@ -35,7 +40,9 @@ class SpaceTreeState extends Equatable {
List<String>? soldCheck, List<String>? soldCheck,
bool? isSearching, bool? isSearching,
Map<String, List<String>>? selectedCommunityAndSpaces, Map<String, List<String>>? selectedCommunityAndSpaces,
String? searchQuery}) { String? searchQuery,
PaginationModel? paginationModel,
bool? paginationIsLoading}) {
return SpaceTreeState( return SpaceTreeState(
communityList: communitiesList ?? this.communityList, communityList: communitiesList ?? this.communityList,
filteredCommunity: filteredCommunity ?? this.filteredCommunity, filteredCommunity: filteredCommunity ?? this.filteredCommunity,
@ -46,7 +53,9 @@ class SpaceTreeState extends Equatable {
soldCheck: soldCheck ?? this.soldCheck, soldCheck: soldCheck ?? this.soldCheck,
isSearching: isSearching ?? this.isSearching, isSearching: isSearching ?? this.isSearching,
selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces, selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces,
searchQuery: searchQuery ?? this.searchQuery); searchQuery: searchQuery ?? this.searchQuery,
paginationModel: paginationModel ?? this.paginationModel,
paginationIsLoading: paginationIsLoading ?? this.paginationIsLoading);
} }
@override @override
@ -60,7 +69,9 @@ class SpaceTreeState extends Equatable {
soldCheck, soldCheck,
isSearching, isSearching,
selectedCommunityAndSpaces, selectedCommunityAndSpaces,
searchQuery searchQuery,
paginationModel,
paginationIsLoading
]; ];
} }

View File

@ -0,0 +1,20 @@
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class PaginationModel {
final int pageNum;
final bool hasNext;
final int size;
final List<CommunityModel> communities;
const PaginationModel(
{required this.pageNum,
required this.hasNext,
required this.size,
required this.communities});
const PaginationModel.emptyConstructor()
: pageNum = 1,
hasNext = true,
size = 10,
communities = const [];
}

View File

@ -34,7 +34,8 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(builder: (context, state) { return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(builder: (context, state) {
List<CommunityModel> list = state.isSearching ? state.filteredCommunity : state.communityList; List<CommunityModel> list =
state.searchQuery.isNotEmpty ? state.filteredCommunity : state.communityList;
return Container( return Container(
height: MediaQuery.sizeOf(context).height, height: MediaQuery.sizeOf(context).height,
decoration: widget.isSide == true decoration: widget.isSide == true
@ -61,7 +62,8 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
borderRadius: const BorderRadius.all(Radius.circular(20)), borderRadius: const BorderRadius.all(Radius.circular(20)),
border: Border.all(color: ColorsManager.grayBorder)), border: Border.all(color: ColorsManager.grayBorder)),
child: TextFormField( child: TextFormField(
style: const TextStyle(color: Colors.black), style: context.textTheme.bodyMedium
?.copyWith(color: ColorsManager.blackColor),
onChanged: (value) { onChanged: (value) {
context.read<SpaceTreeBloc>().add(SearchQueryEvent(value)); context.read<SpaceTreeBloc>().add(SearchQueryEvent(value));
}, },
@ -94,88 +96,101 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Expanded( Expanded(
child: ListView( child: state.isSearching
shrinkWrap: true, ? const Center(child: CircularProgressIndicator())
scrollDirection: Axis.horizontal, : ListView(
children: [ shrinkWrap: true,
Container( scrollDirection: Axis.horizontal,
width: MediaQuery.sizeOf(context).width * 0.5, children: [
padding: const EdgeInsets.all(8.0), Container(
child: list.isEmpty width: MediaQuery.sizeOf(context).width * 0.5,
? Center( padding: const EdgeInsets.all(8.0),
child: Text( child: list.isEmpty
'No results found', ? Center(
style: Theme.of(context).textTheme.bodySmall!.copyWith( child: Text(
color: ColorsManager.lightGrayColor, 'No results found',
fontWeight: FontWeight.w400, style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.lightGrayColor,
fontWeight: FontWeight.w400,
),
), ),
), )
) : Scrollbar(
: Scrollbar( scrollbarOrientation: ScrollbarOrientation.left,
scrollbarOrientation: ScrollbarOrientation.left, thumbVisibility: true,
thumbVisibility: true, controller: _scrollController,
controller: _scrollController, child: NotificationListener(
child: Padding( onNotification: (notification) {
padding: const EdgeInsets.only(left: 16), if (notification is ScrollEndNotification &&
child: ListView( notification.metrics.extentAfter == 0) {
controller: _scrollController, // If the user has reached the end of the list Load more data
shrinkWrap: true, context.read<SpaceTreeBloc>().add(PaginationEvent(
children: list state.paginationModel, state.communityList));
.map( }
(community) => CustomExpansionTileSpaceTree( return false;
title: community.name, },
isSelected: state.selectedCommunities child: Padding(
.contains(community.uuid), padding: const EdgeInsets.only(left: 16),
isSoldCheck: state.selectedCommunities child: ListView.builder(
.contains(community.uuid), shrinkWrap: true,
onExpansionChanged: () { itemCount: list.length,
context controller: _scrollController,
.read<SpaceTreeBloc>() itemBuilder: (context, index) {
.add(OnCommunityExpanded(community.uuid)); return CustomExpansionTileSpaceTree(
}, title: list[index].name,
isExpanded: state.expandedCommunities isSelected: state.selectedCommunities
.contains(community.uuid), .contains(list[index].uuid),
onItemSelected: () { isSoldCheck: state.selectedCommunities
context.read<SpaceTreeBloc>().add( .contains(list[index].uuid),
OnCommunitySelected( onExpansionChanged: () {
community.uuid, community.spaces)); context.read<SpaceTreeBloc>().add(
widget.onSelect(); OnCommunityExpanded(list[index].uuid));
}, },
children: community.spaces.map((space) { isExpanded: state.expandedCommunities
return CustomExpansionTileSpaceTree( .contains(list[index].uuid),
title: space.name, onItemSelected: () {
isExpanded: context.read<SpaceTreeBloc>().add(
state.expandedSpaces.contains(space.uuid), OnCommunitySelected(list[index].uuid,
onItemSelected: () { list[index].spaces));
context.read<SpaceTreeBloc>().add( widget.onSelect();
OnSpaceSelected(community, space.uuid ?? '', },
space.children)); children: list[index].spaces.map((space) {
widget.onSelect(); return CustomExpansionTileSpaceTree(
}, title: space.name,
onExpansionChanged: () { isExpanded: state.expandedSpaces
context.read<SpaceTreeBloc>().add( .contains(space.uuid),
OnSpaceExpanded( onItemSelected: () {
community.uuid, space.uuid ?? '')); context.read<SpaceTreeBloc>().add(
}, OnSpaceSelected(
isSelected: list[index],
state.selectedSpaces.contains(space.uuid) || space.uuid ?? '',
state.soldCheck.contains(space.uuid), space.children));
isSoldCheck: state.soldCheck.contains(space.uuid), widget.onSelect();
children: _buildNestedSpaces( },
context, state, space, community), onExpansionChanged: () {
); context.read<SpaceTreeBloc>().add(
}).toList(), OnSpaceExpanded(list[index].uuid,
), space.uuid ?? ''));
) },
.toList(), isSelected: state.selectedSpaces
), .contains(space.uuid) ||
), state.soldCheck.contains(space.uuid),
), isSoldCheck:
), state.soldCheck.contains(space.uuid),
], children: _buildNestedSpaces(
), context, state, space, list[index]),
);
}).toList(),
);
}),
),
),
),
),
],
),
), ),
if (state.paginationIsLoading) const CircularProgressIndicator(),
// Expanded( // Expanded(
// child: Padding( // child: Padding(
// padding: const EdgeInsets.all(8.0), // padding: const EdgeInsets.all(8.0),

View File

@ -22,11 +22,11 @@ class CommunityModel {
factory CommunityModel.fromJson(Map<String, dynamic> json) { factory CommunityModel.fromJson(Map<String, dynamic> json) {
return CommunityModel( return CommunityModel(
uuid: json['uuid'], uuid: json['uuid'] ?? '',
createdAt: DateTime.parse(json['createdAt']), createdAt: DateTime.parse(json['createdAt'] ?? ''),
updatedAt: DateTime.parse(json['updatedAt']), updatedAt: DateTime.parse(json['updatedAt'] ?? ''),
name: json['name'], name: json['name'] ?? '',
description: json['description'], description: json['description'] ?? '',
region: json['region'] != null ? RegionModel.fromJson(json['region']) : null, region: json['region'] != null ? RegionModel.fromJson(json['region']) : null,
spaces: json['spaces'] != null spaces: json['spaces'] != null
? (json['spaces'] as List).map((space) => SpaceModel.fromJson(space)).toList() ? (json['spaces'] as List).map((space) => SpaceModel.fromJson(space)).toList()

View File

@ -23,9 +23,7 @@ class DevicesManagementApi {
: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId), : ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = communityId.isNotEmpty && spaceId.isNotEmpty List<dynamic> jsonData = json['data'];
? json['data']
: json;
List<AllDevicesModel> devicesList = jsonData.map((jsonItem) { List<AllDevicesModel> devicesList = jsonData.map((jsonItem) {
return AllDevicesModel.fromJson(jsonItem); return AllDevicesModel.fromJson(jsonItem);
}).toList(); }).toList();
@ -93,8 +91,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> deviceBatchControl( Future<bool> deviceBatchControl(List<String> uuids, String code, dynamic value) async {
List<String> uuids, String code, dynamic value) async {
try { try {
final body = { final body = {
'devicesUuid': uuids, 'devicesUuid': uuids,
@ -118,8 +115,7 @@ class DevicesManagementApi {
} }
} }
static Future<List<DeviceModel>> getDevicesByGatewayId( static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
String gatewayId) async {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId), path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
showServerMessage: false, showServerMessage: false,
@ -153,9 +149,7 @@ class DevicesManagementApi {
String code, String code,
) async { ) async {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getDeviceLogs path: ApiEndpoints.getDeviceLogs.replaceAll('{uuid}', uuid).replaceAll('{code}', code),
.replaceAll('{uuid}', uuid)
.replaceAll('{code}', code),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return DeviceReport.fromJson(json); return DeviceReport.fromJson(json);
@ -228,8 +222,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> addScheduleRecord( Future<bool> addScheduleRecord(ScheduleEntry sendSchedule, String uuid) async {
ScheduleEntry sendSchedule, String uuid) async {
try { try {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid), path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
@ -246,8 +239,7 @@ class DevicesManagementApi {
} }
} }
Future<List<ScheduleModel>> getDeviceSchedules( Future<List<ScheduleModel>> getDeviceSchedules(String uuid, String category) async {
String uuid, String category) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getScheduleByDeviceId path: ApiEndpoints.getScheduleByDeviceId
@ -270,9 +262,7 @@ class DevicesManagementApi {
} }
Future<bool> updateScheduleRecord( Future<bool> updateScheduleRecord(
{required bool enable, {required bool enable, required String uuid, required String scheduleId}) async {
required String uuid,
required String scheduleId}) async {
try { try {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.updateScheduleByDeviceId path: ApiEndpoints.updateScheduleByDeviceId
@ -293,8 +283,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> editScheduleRecord( Future<bool> editScheduleRecord(String uuid, ScheduleEntry newSchedule) async {
String uuid, ScheduleEntry newSchedule) async {
try { try {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid), path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/space_tree/model/pagination_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
@ -11,8 +12,7 @@ import 'package:syncrow_web/utils/constants/api_const.dart';
class CommunitySpaceManagementApi { class CommunitySpaceManagementApi {
// Community Management APIs // Community Management APIs
Future<List<CommunityModel>> fetchCommunities(String projectId, Future<List<CommunityModel>> fetchCommunities(String projectId, {int page = 1}) async {
{int page = 1, bool includeSpaces = false}) async {
try { try {
List<CommunityModel> allCommunities = []; List<CommunityModel> allCommunities = [];
bool hasNext = true; bool hasNext = true;
@ -20,7 +20,9 @@ class CommunitySpaceManagementApi {
while (hasNext) { while (hasNext) {
await HTTPService().get( await HTTPService().get(
path: ApiEndpoints.getCommunityList.replaceAll('{projectId}', projectId), path: ApiEndpoints.getCommunityList.replaceAll('{projectId}', projectId),
queryParameters: {'page': page, 'includeSpaces': includeSpaces}, queryParameters: {
'page': page,
},
expectedResponseModel: (json) { expectedResponseModel: (json) {
try { try {
List<dynamic> jsonData = json['data'] ?? []; List<dynamic> jsonData = json['data'] ?? [];
@ -46,6 +48,38 @@ class CommunitySpaceManagementApi {
} }
} }
Future<PaginationModel> fetchCommunitiesAndSpaces(
{required String projectId, int page = 1, String search = ''}) async {
PaginationModel paginationModel = const PaginationModel.emptyConstructor();
try {
bool hasNext = false;
await HTTPService().get(
path: ApiEndpoints.getCommunityList.replaceAll('{projectId}', projectId),
queryParameters: {'page': page, 'includeSpaces': true, 'size': 25, 'search': search},
expectedResponseModel: (json) {
try {
List<dynamic> jsonData = json['data'] ?? [];
hasNext = json['hasNext'] ?? false;
int currentPage = json['page'] ?? 1;
List<CommunityModel> communityList = jsonData.map((jsonItem) {
return CommunityModel.fromJson(jsonItem);
}).toList();
page = currentPage + 1;
paginationModel = PaginationModel(
pageNum: page, hasNext: hasNext, size: 25, communities: communityList);
return paginationModel;
} catch (_) {
hasNext = false;
return [];
}
},
);
} catch (_) {}
return paginationModel;
}
Future<CommunityModel?> getCommunityById(String communityId) async { Future<CommunityModel?> getCommunityById(String communityId) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(