Skip to content

Commit 718b1e7

Browse files
committed
feat(content_management): add shared data loading functionality
- Implement loading of countries and languages in ContentManagementBloc - Add SharedDataRequested event - Extend ContentManagementState to include countries and languages data - Implement fetchAll helper function for efficient data retrieval - Add error handling for data loading operations
1 parent 2177cea commit 718b1e7

File tree

3 files changed

+134
-4
lines changed

3 files changed

+134
-4
lines changed

lib/content_management/bloc/content_management_bloc.dart

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ class ContentManagementBloc
2424
required DataRepository<Headline> headlinesRepository,
2525
required DataRepository<Topic> topicsRepository,
2626
required DataRepository<Source> sourcesRepository,
27-
}) : _headlinesRepository = headlinesRepository,
28-
_topicsRepository = topicsRepository,
29-
_sourcesRepository = sourcesRepository,
30-
super(const ContentManagementState()) {
27+
required DataRepository<Country> countriesRepository,
28+
required DataRepository<Language> languagesRepository,
29+
}) : _headlinesRepository = headlinesRepository,
30+
_topicsRepository = topicsRepository,
31+
_sourcesRepository = sourcesRepository,
32+
_countriesRepository = countriesRepository,
33+
_languagesRepository = languagesRepository,
34+
super(const ContentManagementState()) {
35+
on<SharedDataRequested>(_onSharedDataRequested);
3136
on<ContentManagementTabChanged>(_onContentManagementTabChanged);
3237
on<LoadHeadlinesRequested>(_onLoadHeadlinesRequested);
3338
on<HeadlineUpdated>(_onHeadlineUpdated);
@@ -43,6 +48,94 @@ class ContentManagementBloc
4348
final DataRepository<Headline> _headlinesRepository;
4449
final DataRepository<Topic> _topicsRepository;
4550
final DataRepository<Source> _sourcesRepository;
51+
final DataRepository<Country> _countriesRepository;
52+
final DataRepository<Language> _languagesRepository;
53+
54+
Future<void> _onSharedDataRequested(
55+
SharedDataRequested event,
56+
Emitter<ContentManagementState> emit,
57+
) async {
58+
// Helper function to fetch all items of a given type.
59+
Future<List<T>> fetchAll<T>({
60+
required DataRepository<T> repository,
61+
required List<SortOption> sort,
62+
}) async {
63+
final allItems = <T>[];
64+
String? cursor;
65+
bool hasMore;
66+
67+
do {
68+
final response = await repository.readAll(
69+
sort: sort,
70+
pagination: PaginationOptions(cursor: cursor),
71+
filter: {'status': ContentStatus.active.name},
72+
);
73+
allItems.addAll(response.items);
74+
cursor = response.cursor;
75+
hasMore = response.hasMore;
76+
} while (hasMore);
77+
78+
return allItems;
79+
}
80+
81+
// Check if data is already loaded or is currently loading to prevent
82+
// redundant fetches.
83+
if (state.allCountriesStatus == ContentManagementStatus.success &&
84+
state.allLanguagesStatus == ContentManagementStatus.success) {
85+
return;
86+
}
87+
88+
// Set loading status for both lists.
89+
emit(
90+
state.copyWith(
91+
allCountriesStatus: ContentManagementStatus.loading,
92+
allLanguagesStatus: ContentManagementStatus.loading,
93+
),
94+
);
95+
96+
try {
97+
// Fetch both lists in parallel.
98+
final results = await Future.wait([
99+
fetchAll<Country>(
100+
repository: _countriesRepository,
101+
sort: [const SortOption('name', SortOrder.asc)],
102+
),
103+
fetchAll<Language>(
104+
repository: _languagesRepository,
105+
sort: [const SortOption('name', SortOrder.asc)],
106+
),
107+
]);
108+
109+
final countries = results[0] as List<Country>;
110+
final languages = results[1] as List<Language>;
111+
112+
// Update the state with the complete lists.
113+
emit(
114+
state.copyWith(
115+
allCountries: countries,
116+
allCountriesStatus: ContentManagementStatus.success,
117+
allLanguages: languages,
118+
allLanguagesStatus: ContentManagementStatus.success,
119+
),
120+
);
121+
} on HttpException catch (e) {
122+
emit(
123+
state.copyWith(
124+
allCountriesStatus: ContentManagementStatus.failure,
125+
allLanguagesStatus: ContentManagementStatus.failure,
126+
exception: e,
127+
),
128+
);
129+
} catch (e) {
130+
emit(
131+
state.copyWith(
132+
allCountriesStatus: ContentManagementStatus.failure,
133+
allLanguagesStatus: ContentManagementStatus.failure,
134+
exception: UnknownException('An unexpected error occurred: $e'),
135+
),
136+
);
137+
}
138+
}
46139

47140
void _onContentManagementTabChanged(
48141
ContentManagementTabChanged event,

lib/content_management/bloc/content_management_event.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,12 @@ final class SourceUpdated extends ContentManagementEvent {
155155
@override
156156
List<Object?> get props => [source];
157157
}
158+
159+
/// {@template shared_data_requested}
160+
/// Event to request loading of shared data like countries and languages.
161+
/// This should be dispatched once when the content management section is loaded.
162+
/// {@endtemplate}
163+
final class SharedDataRequested extends ContentManagementEvent {
164+
/// {@macro shared_data_requested}
165+
const SharedDataRequested();
166+
}

lib/content_management/bloc/content_management_state.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class ContentManagementState extends Equatable {
3232
this.sources = const [],
3333
this.sourcesCursor,
3434
this.sourcesHasMore = false,
35+
this.allCountriesStatus = ContentManagementStatus.initial,
36+
this.allCountries = const [],
37+
this.allLanguagesStatus = ContentManagementStatus.initial,
38+
this.allLanguages = const [],
3539
this.exception,
3640
});
3741

@@ -74,6 +78,18 @@ class ContentManagementState extends Equatable {
7478
/// Indicates if there are more sources to load.
7579
final bool sourcesHasMore;
7680

81+
/// Status of all countries data operations.
82+
final ContentManagementStatus allCountriesStatus;
83+
84+
/// Cached list of all countries.
85+
final List<Country> allCountries;
86+
87+
/// Status of all languages data operations.
88+
final ContentManagementStatus allLanguagesStatus;
89+
90+
/// Cached list of all languages.
91+
final List<Language> allLanguages;
92+
7793
/// The error describing an operation failure, if any.
7894
final HttpException? exception;
7995

@@ -92,6 +108,10 @@ class ContentManagementState extends Equatable {
92108
List<Source>? sources,
93109
String? sourcesCursor,
94110
bool? sourcesHasMore,
111+
ContentManagementStatus? allCountriesStatus,
112+
List<Country>? allCountries,
113+
ContentManagementStatus? allLanguagesStatus,
114+
List<Language>? allLanguages,
95115
HttpException? exception,
96116
}) {
97117
return ContentManagementState(
@@ -108,6 +128,10 @@ class ContentManagementState extends Equatable {
108128
sources: sources ?? this.sources,
109129
sourcesCursor: sourcesCursor ?? this.sourcesCursor,
110130
sourcesHasMore: sourcesHasMore ?? this.sourcesHasMore,
131+
allCountriesStatus: allCountriesStatus ?? this.allCountriesStatus,
132+
allCountries: allCountries ?? this.allCountries,
133+
allLanguagesStatus: allLanguagesStatus ?? this.allLanguagesStatus,
134+
allLanguages: allLanguages ?? this.allLanguages,
111135
exception: exception ?? this.exception,
112136
);
113137
}
@@ -127,6 +151,10 @@ class ContentManagementState extends Equatable {
127151
sources,
128152
sourcesCursor,
129153
sourcesHasMore,
154+
allCountriesStatus,
155+
allCountries,
156+
allLanguagesStatus,
157+
allLanguages,
130158
exception,
131159
];
132160
}

0 commit comments

Comments
 (0)