Skip to content

Commit b50a700

Browse files
committed
fix(data): correctly apply custom filters and pagination in CountryInMemoryClient
- Add static filter keys for active sources and headlines - Modify readAll method to fetch all items before applying custom filters - Implement manual pagination after filtering - Preserve hasMore logic and cursor for paginated responses
1 parent 41c9b7d commit b50a700

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

lib/shared/data/clients/country_inmemory_client.dart

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,20 @@ class CountryInMemoryClient implements DataClient<Country> {
2121
required DataClient<Country> decoratedClient,
2222
required List<Source> allSources,
2323
required List<Headline> allHeadlines,
24-
}) : _decoratedClient = decoratedClient,
25-
_allSources = allSources,
26-
_allHeadlines = allHeadlines;
24+
}) : _decoratedClient = decoratedClient,
25+
_allSources = allSources,
26+
_allHeadlines = allHeadlines;
2727

2828
final DataClient<Country> _decoratedClient;
2929
final List<Source> _allSources;
3030
final List<Headline> _allHeadlines;
3131

32+
/// Filter key for checking if a country has active sources.
33+
static const String hasActiveSourcesFilter = 'hasActiveSources';
34+
35+
/// Filter key for checking if a country has active headlines.
36+
static const String hasActiveHeadlinesFilter = 'hasActiveHeadlines';
37+
3238
@override
3339
Future<SuccessApiResponse<List<Map<String, dynamic>>>> aggregate({
3440
required List<Map<String, dynamic>> pipeline,
@@ -73,32 +79,33 @@ class CountryInMemoryClient implements DataClient<Country> {
7379
PaginationOptions? pagination,
7480
List<SortOption>? sort,
7581
}) async {
76-
// First, get the initial list of countries from the decorated client.
77-
// This handles generic filters, sorting, and pagination.
78-
final response = await _decoratedClient.readAll(
82+
// Fetch ALL items from the decorated client first,
83+
// then apply custom filters, and finally apply pagination.
84+
// This ensures correct pagination behavior with custom filters.
85+
final allItemsResponse = await _decoratedClient.readAll(
7986
userId: userId,
8087
filter: filter,
81-
pagination: pagination,
88+
// Pass null for pagination to get all items, as custom filters
89+
// need to operate on the complete dataset before pagination.
90+
pagination: null,
8291
sort: sort,
8392
);
8493

85-
var filteredCountries = response.data.items;
94+
Iterable<Country> filteredCountriesIterable = allItemsResponse.data.items;
8695

8796
// Apply custom filters if present
88-
final hasActiveSources = filter?['hasActiveSources'] == true;
89-
final hasActiveHeadlines = filter?['hasActiveHeadlines'] == true;
97+
final hasActiveSources = filter?[hasActiveSourcesFilter] == true;
98+
final hasActiveHeadlines = filter?[hasActiveHeadlinesFilter] == true;
9099

91100
if (hasActiveSources) {
92101
final countriesWithActiveSources = _allSources
93102
.where((source) => source.status == ContentStatus.active)
94103
.map((source) => source.headquarters.id)
95104
.toSet();
96105

97-
filteredCountries = filteredCountries
98-
.where(
99-
(country) => countriesWithActiveSources.contains(country.id),
100-
)
101-
.toList();
106+
filteredCountriesIterable = filteredCountriesIterable.where(
107+
(country) => countriesWithActiveSources.contains(country.id),
108+
);
102109
}
103110

104111
if (hasActiveHeadlines) {
@@ -107,19 +114,33 @@ class CountryInMemoryClient implements DataClient<Country> {
107114
.map((headline) => headline.eventCountry.id)
108115
.toSet();
109116

110-
filteredCountries = filteredCountries
111-
.where(
112-
(country) => countriesWithActiveHeadlines.contains(country.id),
113-
)
114-
.toList();
117+
filteredCountriesIterable = filteredCountriesIterable.where(
118+
(country) => countriesWithActiveHeadlines.contains(country.id),
119+
);
115120
}
116121

117-
// Return a new PaginatedResponse with the potentially further filtered items.
118-
// The cursor and hasMore logic from the original response are preserved,
119-
// but the items list is updated.
122+
// Manually apply pagination to the filtered list.
123+
final offset = pagination?.cursor != null
124+
? int.tryParse(pagination!.cursor!) ?? 0
125+
: 0;
126+
final limit = pagination?.limit ?? filteredCountriesIterable.length;
127+
128+
final paginatedItems = filteredCountriesIterable
129+
.skip(offset)
130+
.take(limit)
131+
.toList();
132+
133+
final hasMore = (offset + limit) < filteredCountriesIterable.length;
134+
final nextCursor = hasMore ? (offset + limit).toString() : null;
135+
136+
// Return a new PaginatedResponse with the correctly filtered and paginated items.
120137
return SuccessApiResponse(
121-
data: response.data.copyWith(items: filteredCountries),
122-
metadata: response.metadata,
138+
data: PaginatedResponse(
139+
items: paginatedItems,
140+
cursor: nextCursor,
141+
hasMore: hasMore,
142+
),
143+
metadata: allItemsResponse.metadata,
123144
);
124145
}
125146

0 commit comments

Comments
 (0)