Skip to content

Commit e26dbb2

Browse files
committed
feat(data_client): add CountryInMemoryClient for enhanced country filtering
- Implement CountryInMemoryClient to filter countries based on active sources and headlines - Extend DataClient<Country> with custom logic for hasActiveSources and hasActiveHeadlines filters - Use static fixture data for filtering operations - Delegate standard DataClient methods to a wrapped DataClient<Country> instance
1 parent 79bcdd5 commit e26dbb2

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import 'package:core/core.dart';
2+
import 'package:data_client/data_client.dart';
3+
4+
/// {@template country_inmemory_client}
5+
/// A specialized in-memory data client for [Country] models that extends
6+
/// the functionality of a generic [DataClient<Country>] by adding custom
7+
/// filtering logic for `hasActiveSources` and `hasActiveHeadlines` filters.
8+
///
9+
/// This client acts as a decorator, wrapping an existing [DataClient<Country>]
10+
/// (typically [DataInMemory<Country>]) and intercepting `readAll` calls
11+
/// to apply application-specific filtering using static fixture data.
12+
/// All other [DataClient] methods are delegated directly to the wrapped client.
13+
/// {@endtemplate}
14+
class CountryInMemoryClient implements DataClient<Country> {
15+
/// {@macro country_inmemory_client}
16+
///
17+
/// Requires a [decoratedClient] to which standard data operations will be
18+
/// delegated. Also requires [allSources] and [allHeadlines] (typically
19+
/// static fixture data from the `core` package) to perform custom filtering.
20+
const CountryInMemoryClient({
21+
required DataClient<Country> decoratedClient,
22+
required List<Source> allSources,
23+
required List<Headline> allHeadlines,
24+
}) : _decoratedClient = decoratedClient,
25+
_allSources = allSources,
26+
_allHeadlines = allHeadlines;
27+
28+
final DataClient<Country> _decoratedClient;
29+
final List<Source> _allSources;
30+
final List<Headline> _allHeadlines;
31+
32+
@override
33+
Future<SuccessApiResponse<List<Map<String, dynamic>>>> aggregate({
34+
required List<Map<String, dynamic>> pipeline,
35+
String? userId,
36+
}) {
37+
return _decoratedClient.aggregate(pipeline: pipeline, userId: userId);
38+
}
39+
40+
@override
41+
Future<SuccessApiResponse<int>> count({
42+
String? userId,
43+
Map<String, dynamic>? filter,
44+
}) {
45+
return _decoratedClient.count(userId: userId, filter: filter);
46+
}
47+
48+
@override
49+
Future<SuccessApiResponse<Country>> create({
50+
required Country item,
51+
String? userId,
52+
}) {
53+
return _decoratedClient.create(item: item, userId: userId);
54+
}
55+
56+
@override
57+
Future<void> delete({required String id, String? userId}) {
58+
return _decoratedClient.delete(id: id, userId: userId);
59+
}
60+
61+
@override
62+
Future<SuccessApiResponse<Country>> read({
63+
required String id,
64+
String? userId,
65+
}) {
66+
return _decoratedClient.read(id: id, userId: userId);
67+
}
68+
69+
@override
70+
Future<SuccessApiResponse<PaginatedResponse<Country>>> readAll({
71+
String? userId,
72+
Map<String, dynamic>? filter,
73+
PaginationOptions? pagination,
74+
List<SortOption>? sort,
75+
}) 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(
79+
userId: userId,
80+
filter: filter,
81+
pagination: pagination,
82+
sort: sort,
83+
);
84+
85+
var filteredCountries = response.data.items;
86+
87+
// Apply custom filters if present
88+
final hasActiveSources = filter?['hasActiveSources'] == true;
89+
final hasActiveHeadlines = filter?['hasActiveHeadlines'] == true;
90+
91+
if (hasActiveSources) {
92+
final countriesWithActiveSources = _allSources
93+
.where((source) => source.status == ContentStatus.active)
94+
.map((source) => source.headquarters.id)
95+
.toSet();
96+
97+
filteredCountries = filteredCountries
98+
.where(
99+
(country) => countriesWithActiveSources.contains(country.id),
100+
)
101+
.toList();
102+
}
103+
104+
if (hasActiveHeadlines) {
105+
final countriesWithActiveHeadlines = _allHeadlines
106+
.where((headline) => headline.status == ContentStatus.active)
107+
.map((headline) => headline.eventCountry.id)
108+
.toSet();
109+
110+
filteredCountries = filteredCountries
111+
.where(
112+
(country) => countriesWithActiveHeadlines.contains(country.id),
113+
)
114+
.toList();
115+
}
116+
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.
120+
return SuccessApiResponse(
121+
data: response.data.copyWith(items: filteredCountries),
122+
metadata: response.metadata,
123+
);
124+
}
125+
126+
@override
127+
Future<SuccessApiResponse<Country>> update({
128+
required String id,
129+
required Country item,
130+
String? userId,
131+
}) {
132+
return _decoratedClient.update(id: id, item: item, userId: userId);
133+
}
134+
}

0 commit comments

Comments
 (0)