From 0ad8093cc1fc8cd25edfe846a2edfec2c8656ac5 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:12:53 +0100 Subject: [PATCH 01/17] refactor(content_management): remove unused country search changed event - Remove CreateHeadlineCountrySearchChanged event from create_headline_event.dart - This event was likely unused and could lead to confusion or unexpected behavior --- .../bloc/create_headline/create_headline_event.dart | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/content_management/bloc/create_headline/create_headline_event.dart b/lib/content_management/bloc/create_headline/create_headline_event.dart index b2dd90df..f93a664f 100644 --- a/lib/content_management/bloc/create_headline/create_headline_event.dart +++ b/lib/content_management/bloc/create_headline/create_headline_event.dart @@ -84,14 +84,6 @@ final class CreateHeadlineSubmitted extends CreateHeadlineEvent { const CreateHeadlineSubmitted(); } -/// Event for when the country search term is changed. -final class CreateHeadlineCountrySearchChanged extends CreateHeadlineEvent { - const CreateHeadlineCountrySearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more countries. final class CreateHeadlineLoadMoreCountriesRequested extends CreateHeadlineEvent { From 0004980854faff3015be6b234d49b7b7e653b1d5 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:14:55 +0100 Subject: [PATCH 02/17] refactor(content_management): remove country search functionality - Remove _onCountrySearchChanged method and its associated event - Remove droppable transformer from CreateHeadlineCountrySearchChanged event - Adjust country load more functionality to not consider search term --- .../create_headline/create_headline_bloc.dart | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/lib/content_management/bloc/create_headline/create_headline_bloc.dart b/lib/content_management/bloc/create_headline/create_headline_bloc.dart index 456fb6a7..9c0da77a 100644 --- a/lib/content_management/bloc/create_headline/create_headline_bloc.dart +++ b/lib/content_management/bloc/create_headline/create_headline_bloc.dart @@ -35,10 +35,6 @@ class CreateHeadlineBloc on(_onCountryChanged); on(_onStatusChanged); on(_onSubmitted); - on( - _onCountrySearchChanged, - transformer: droppable(), - ); on(_onLoadMoreCountriesRequested); } @@ -195,37 +191,6 @@ class CreateHeadlineBloc } } - Future _onCountrySearchChanged( - CreateHeadlineCountrySearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(countrySearchTerm: event.searchTerm)); - try { - final countriesResponse = await _countriesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - countries: countriesResponse.items, - countriesCursor: countriesResponse.cursor, - countriesHasMore: countriesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: CreateHeadlineStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: CreateHeadlineStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreCountriesRequested( CreateHeadlineLoadMoreCountriesRequested event, Emitter emit, @@ -239,9 +204,6 @@ class CreateHeadlineBloc pagination: state.countriesCursor != null ? PaginationOptions(cursor: state.countriesCursor) : null, - filter: state.countrySearchTerm.isNotEmpty - ? {'name': state.countrySearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); From 2598648a080b6faf214367c109873e1074365fc6 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:15:14 +0100 Subject: [PATCH 03/17] refactor(create_headline): remove unused country search term - Remove countrySearchTerm from CreateHeadlineState - Update constructors and copyWith method to reflect the removal - Simplify the state class by removing unused properties --- .../bloc/create_headline/create_headline_state.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/content_management/bloc/create_headline/create_headline_state.dart b/lib/content_management/bloc/create_headline/create_headline_state.dart index f4effd41..1fb3f0c9 100644 --- a/lib/content_management/bloc/create_headline/create_headline_state.dart +++ b/lib/content_management/bloc/create_headline/create_headline_state.dart @@ -35,7 +35,6 @@ final class CreateHeadlineState extends Equatable { this.countriesHasMore = true, this.countriesIsLoadingMore = false, this.countriesCursor, - this.countrySearchTerm = '', this.contentStatus = ContentStatus.active, this.exception, this.createdHeadline, @@ -55,7 +54,6 @@ final class CreateHeadlineState extends Equatable { final bool countriesHasMore; final bool countriesIsLoadingMore; final String? countriesCursor; - final String countrySearchTerm; final ContentStatus contentStatus; final HttpException? exception; final Headline? createdHeadline; @@ -85,7 +83,6 @@ final class CreateHeadlineState extends Equatable { bool? countriesHasMore, bool? countriesIsLoadingMore, String? countriesCursor, - String? countrySearchTerm, ContentStatus? contentStatus, HttpException? exception, Headline? createdHeadline, @@ -106,7 +103,6 @@ final class CreateHeadlineState extends Equatable { countriesIsLoadingMore: countriesIsLoadingMore ?? this.countriesIsLoadingMore, countriesCursor: countriesCursor ?? this.countriesCursor, - countrySearchTerm: countrySearchTerm ?? this.countrySearchTerm, contentStatus: contentStatus ?? this.contentStatus, exception: exception, createdHeadline: createdHeadline ?? this.createdHeadline, @@ -129,7 +125,6 @@ final class CreateHeadlineState extends Equatable { countriesHasMore, countriesIsLoadingMore, countriesCursor, - countrySearchTerm, contentStatus, exception, createdHeadline, From 5b3b67c2f6ad2a89c2b9e340277bad980235f390 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:16:03 +0100 Subject: [PATCH 04/17] refactor(content_management): replace SearchableDropdownFormField with DropdownButtonFormField - Replace custom SearchableDropdownFormField with standard DropdownButtonFormField for country selection - Simplify the UI by removing searchable functionality and pagination - Add "None" option as the first dropdown item - Display load more option when there are more countries available --- .../view/create_headline_page.dart | 89 +++++++++---------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/lib/content_management/view/create_headline_page.dart b/lib/content_management/view/create_headline_page.dart index 70dfc29c..9ba9fea1 100644 --- a/lib/content_management/view/create_headline_page.dart +++ b/lib/content_management/view/create_headline_page.dart @@ -214,57 +214,50 @@ class _CreateHeadlineViewState extends State<_CreateHeadlineView> { .add(CreateHeadlineTopicChanged(value)), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.countryName, - bloc: context.read(), - initialValue: state.eventCountry, - itemsExtractor: (state) => state.countries, - hasMoreExtractor: (state) => state.countriesHasMore, - isLoadingExtractor: (state) => - state.status == CreateHeadlineStatus.loading, - onChanged: (value) => context - .read() - .add(CreateHeadlineCountryChanged(value)), - onSearchChanged: (value) => context - .read() - .add(CreateHeadlineCountrySearchChanged(value)), - onLoadMore: () => context.read().add( - const CreateHeadlineLoadMoreCountriesRequested(), - ), - itemBuilder: (context, country) { - return ListTile( - leading: SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), + DropdownButtonFormField( + value: state.eventCountry, + decoration: InputDecoration( + labelText: l10n.countryName, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.countries.map( + (country) => DropdownMenuItem( + value: country, + child: Row( + children: [ + SizedBox( + width: 32, + height: 20, + child: Image.network( + country.flagUrl, + fit: BoxFit.cover, + errorBuilder: + (context, error, stackTrace) => + const Icon(Icons.flag), + ), + ), + const SizedBox(width: AppSpacing.md), + Text(country.name), + ], ), ), - title: Text(country.name), - ); - }, - selectedItemBuilder: (context, country) { - return Row( - children: [ - SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), - ), + ), + if (state.countriesHasMore) + DropdownMenuItem( + value: null, + child: Center( + child: Text(l10n.loadMore), ), - const SizedBox(width: AppSpacing.md), - Text(country.name), - ], - ); - }, + onTap: () => context.read().add( + const CreateHeadlineLoadMoreCountriesRequested(), + ), + ), + ], + onChanged: (value) => context + .read() + .add(CreateHeadlineCountryChanged(value)), ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField( From 5628a4198a757a4721977282f4e50378e2329cce Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:18:38 +0100 Subject: [PATCH 05/17] refactor(content_management): remove unused country search event - Remove EditHeadlineCountrySearchChanged event from edit_headline_event.dart - This event was likely unused and unnecessary, simplifying the event structure --- .../bloc/edit_headline/edit_headline_event.dart | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/content_management/bloc/edit_headline/edit_headline_event.dart b/lib/content_management/bloc/edit_headline/edit_headline_event.dart index f07256d6..31de4957 100644 --- a/lib/content_management/bloc/edit_headline/edit_headline_event.dart +++ b/lib/content_management/bloc/edit_headline/edit_headline_event.dart @@ -84,14 +84,6 @@ final class EditHeadlineSubmitted extends EditHeadlineEvent { const EditHeadlineSubmitted(); } -/// Event for when the country search term is changed. -final class EditHeadlineCountrySearchChanged extends EditHeadlineEvent { - const EditHeadlineCountrySearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more countries. final class EditHeadlineLoadMoreCountriesRequested extends EditHeadlineEvent { const EditHeadlineLoadMoreCountriesRequested(); From 9474d04f62f036d2bf91d8e743da6697997ce6c9 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:18:50 +0100 Subject: [PATCH 06/17] fix(content_management): replace localization with static text for country load more option - Replaced l10n.loadMore with 'Load More' text - Added const keyword for Center and Text widgets --- lib/content_management/view/create_headline_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/content_management/view/create_headline_page.dart b/lib/content_management/view/create_headline_page.dart index 9ba9fea1..58296514 100644 --- a/lib/content_management/view/create_headline_page.dart +++ b/lib/content_management/view/create_headline_page.dart @@ -247,8 +247,8 @@ class _CreateHeadlineViewState extends State<_CreateHeadlineView> { if (state.countriesHasMore) DropdownMenuItem( value: null, - child: Center( - child: Text(l10n.loadMore), + child: const Center( + child: Text('Load More'), ), onTap: () => context.read().add( const CreateHeadlineLoadMoreCountriesRequested(), From 5fdc6ec2904ee889f89aeec94d6a8d105626dba9 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:19:59 +0100 Subject: [PATCH 07/17] refactor(content_management): remove unused country search term from edit headline state - Remove countrySearchTerm field from EditHeadlineState - Remove countrySearchTerm parameter from EditHeadlineState constructor - Remove countrySearchTerm from copyWith method - Remove countrySearchTerm from props list in EditHeadlineState --- .../bloc/edit_headline/edit_headline_state.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/content_management/bloc/edit_headline/edit_headline_state.dart b/lib/content_management/bloc/edit_headline/edit_headline_state.dart index 804e639b..30688de8 100644 --- a/lib/content_management/bloc/edit_headline/edit_headline_state.dart +++ b/lib/content_management/bloc/edit_headline/edit_headline_state.dart @@ -36,7 +36,6 @@ final class EditHeadlineState extends Equatable { this.countriesHasMore = true, this.countriesIsLoadingMore = false, this.countriesCursor, - this.countrySearchTerm = '', this.contentStatus = ContentStatus.active, this.exception, this.updatedHeadline, @@ -57,7 +56,6 @@ final class EditHeadlineState extends Equatable { final bool countriesHasMore; final bool countriesIsLoadingMore; final String? countriesCursor; - final String countrySearchTerm; final ContentStatus contentStatus; final HttpException? exception; final Headline? updatedHeadline; @@ -88,7 +86,6 @@ final class EditHeadlineState extends Equatable { bool? countriesHasMore, bool? countriesIsLoadingMore, String? countriesCursor, - String? countrySearchTerm, ContentStatus? contentStatus, HttpException? exception, Headline? updatedHeadline, @@ -110,7 +107,6 @@ final class EditHeadlineState extends Equatable { countriesIsLoadingMore: countriesIsLoadingMore ?? this.countriesIsLoadingMore, countriesCursor: countriesCursor ?? this.countriesCursor, - countrySearchTerm: countrySearchTerm ?? this.countrySearchTerm, contentStatus: contentStatus ?? this.contentStatus, exception: exception, updatedHeadline: updatedHeadline ?? this.updatedHeadline, @@ -134,7 +130,6 @@ final class EditHeadlineState extends Equatable { countriesHasMore, countriesIsLoadingMore, countriesCursor, - countrySearchTerm, contentStatus, exception, updatedHeadline, From f7ff2b72b348ce997ac21059f51493cbedded9e6 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:22:59 +0100 Subject: [PATCH 08/17] refactor(content_management): remove country search functionality - Remove _onCountrySearchChanged method - Remove EditHeadlineCountrySearchChanged event handler - Remove state related to country search term - Remove filter logic in _onLoadMoreCountriesRequested based on search term --- .../edit_headline/edit_headline_bloc.dart | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/lib/content_management/bloc/edit_headline/edit_headline_bloc.dart b/lib/content_management/bloc/edit_headline/edit_headline_bloc.dart index c1129e03..f280c480 100644 --- a/lib/content_management/bloc/edit_headline/edit_headline_bloc.dart +++ b/lib/content_management/bloc/edit_headline/edit_headline_bloc.dart @@ -35,10 +35,6 @@ class EditHeadlineBloc extends Bloc { on(_onCountryChanged); on(_onStatusChanged); on(_onSubmitted); - on( - _onCountrySearchChanged, - transformer: droppable(), - ); on( _onLoadMoreCountriesRequested, ); @@ -245,37 +241,6 @@ class EditHeadlineBloc extends Bloc { } } - Future _onCountrySearchChanged( - EditHeadlineCountrySearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(countrySearchTerm: event.searchTerm)); - try { - final countriesResponse = await _countriesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - countries: countriesResponse.items, - countriesCursor: countriesResponse.cursor, - countriesHasMore: countriesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: EditHeadlineStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: EditHeadlineStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreCountriesRequested( EditHeadlineLoadMoreCountriesRequested event, Emitter emit, @@ -289,9 +254,6 @@ class EditHeadlineBloc extends Bloc { pagination: state.countriesCursor != null ? PaginationOptions(cursor: state.countriesCursor) : null, - filter: state.countrySearchTerm.isNotEmpty - ? {'name': state.countrySearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); From 2828084ded20a10892ff71b8bb94539ffe61c4a5 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:23:16 +0100 Subject: [PATCH 09/17] refactor(content_management): replace SearchableDropdownFormField with DropdownButtonFormField - Replace custom SearchableDropdownFormField with DropdownButtonFormField for country selection - Simplify the UI for better maintainability and readability - Improve performance by removing unnecessary search and load more functionality --- .../view/edit_headline_page.dart | 89 +++++++++---------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/lib/content_management/view/edit_headline_page.dart b/lib/content_management/view/edit_headline_page.dart index b0b9df23..5b5b0063 100644 --- a/lib/content_management/view/edit_headline_page.dart +++ b/lib/content_management/view/edit_headline_page.dart @@ -282,57 +282,50 @@ class _EditHeadlineViewState extends State<_EditHeadlineView> { .add(EditHeadlineTopicChanged(value)), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.countryName, - bloc: context.read(), - initialValue: selectedCountry, - itemsExtractor: (state) => state.countries, - hasMoreExtractor: (state) => state.countriesHasMore, - isLoadingExtractor: (state) => - state.status == EditHeadlineStatus.loading, - onChanged: (value) => context - .read() - .add(EditHeadlineCountryChanged(value)), - onSearchChanged: (value) => context - .read() - .add(EditHeadlineCountrySearchChanged(value)), - onLoadMore: () => context.read().add( - const EditHeadlineLoadMoreCountriesRequested(), - ), - itemBuilder: (context, country) { - return ListTile( - leading: SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), + DropdownButtonFormField( + value: selectedCountry, + decoration: InputDecoration( + labelText: l10n.countryName, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.countries.map( + (country) => DropdownMenuItem( + value: country, + child: Row( + children: [ + SizedBox( + width: 32, + height: 20, + child: Image.network( + country.flagUrl, + fit: BoxFit.cover, + errorBuilder: + (context, error, stackTrace) => + const Icon(Icons.flag), + ), + ), + const SizedBox(width: AppSpacing.md), + Text(country.name), + ], ), ), - title: Text(country.name), - ); - }, - selectedItemBuilder: (context, country) { - return Row( - children: [ - SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), - ), + ), + if (state.countriesHasMore) + DropdownMenuItem( + value: null, + child: const Center( + child: Text('Load More'), ), - const SizedBox(width: AppSpacing.md), - Text(country.name), - ], - ); - }, + onTap: () => context.read().add( + const EditHeadlineLoadMoreCountriesRequested(), + ), + ), + ], + onChanged: (value) => context + .read() + .add(EditHeadlineCountryChanged(value)), ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField( From 720d239cd6b965dd1debffdf780f552d1b241d4f Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:24:52 +0100 Subject: [PATCH 10/17] refactor(content_management): remove unused search change events - Remove CreateSourceCountrySearchChanged and CreateSourceLanguageSearchChanged events - These events were not used in the bloc logic and have been removed to simplify the codebase --- .../bloc/create_source/create_source_event.dart | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/lib/content_management/bloc/create_source/create_source_event.dart b/lib/content_management/bloc/create_source/create_source_event.dart index d15f2f4e..739cc3f4 100644 --- a/lib/content_management/bloc/create_source/create_source_event.dart +++ b/lib/content_management/bloc/create_source/create_source_event.dart @@ -76,27 +76,11 @@ final class CreateSourceSubmitted extends CreateSourceEvent { const CreateSourceSubmitted(); } -/// Event for when the country search term is changed. -final class CreateSourceCountrySearchChanged extends CreateSourceEvent { - const CreateSourceCountrySearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more countries. final class CreateSourceLoadMoreCountriesRequested extends CreateSourceEvent { const CreateSourceLoadMoreCountriesRequested(); } -/// Event for when the language search term is changed. -final class CreateSourceLanguageSearchChanged extends CreateSourceEvent { - const CreateSourceLanguageSearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more languages. final class CreateSourceLoadMoreLanguagesRequested extends CreateSourceEvent { const CreateSourceLoadMoreLanguagesRequested(); From 0e0cb3785bfe4c21090567e47928c5622accfff6 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:25:04 +0100 Subject: [PATCH 11/17] refactor(content_management): remove country and language search terms - Remove countrySearchTerm and languageSearchTerm properties from CreateSourceState --- .../create_source/create_source_state.dart | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/lib/content_management/bloc/create_source/create_source_state.dart b/lib/content_management/bloc/create_source/create_source_state.dart index cc0aef6e..2d451561 100644 --- a/lib/content_management/bloc/create_source/create_source_state.dart +++ b/lib/content_management/bloc/create_source/create_source_state.dart @@ -33,12 +33,10 @@ final class CreateSourceState extends Equatable { this.countriesHasMore = true, this.countriesIsLoadingMore = false, this.countriesCursor, - this.countrySearchTerm = '', this.languages = const [], this.languagesHasMore = true, this.languagesIsLoadingMore = false, this.languagesCursor, - this.languageSearchTerm = '', this.contentStatus = ContentStatus.active, this.exception, this.createdSource, @@ -55,12 +53,10 @@ final class CreateSourceState extends Equatable { final bool countriesHasMore; final bool countriesIsLoadingMore; final String? countriesCursor; - final String countrySearchTerm; final List languages; final bool languagesHasMore; final bool languagesIsLoadingMore; final String? languagesCursor; - final String languageSearchTerm; final ContentStatus contentStatus; final HttpException? exception; final Source? createdSource; @@ -86,12 +82,10 @@ final class CreateSourceState extends Equatable { bool? countriesHasMore, bool? countriesIsLoadingMore, String? countriesCursor, - String? countrySearchTerm, List? languages, bool? languagesHasMore, bool? languagesIsLoadingMore, String? languagesCursor, - String? languageSearchTerm, ContentStatus? contentStatus, HttpException? exception, Source? createdSource, @@ -109,13 +103,11 @@ final class CreateSourceState extends Equatable { countriesIsLoadingMore: countriesIsLoadingMore ?? this.countriesIsLoadingMore, countriesCursor: countriesCursor ?? this.countriesCursor, - countrySearchTerm: countrySearchTerm ?? this.countrySearchTerm, languages: languages ?? this.languages, languagesHasMore: languagesHasMore ?? this.languagesHasMore, languagesIsLoadingMore: languagesIsLoadingMore ?? this.languagesIsLoadingMore, languagesCursor: languagesCursor ?? this.languagesCursor, - languageSearchTerm: languageSearchTerm ?? this.languageSearchTerm, contentStatus: contentStatus ?? this.contentStatus, exception: exception, createdSource: createdSource ?? this.createdSource, @@ -133,16 +125,14 @@ final class CreateSourceState extends Equatable { headquarters, countries, countriesHasMore, - countriesIsLoadingMore, - countriesCursor, - countrySearchTerm, - languages, - languagesHasMore, - languagesIsLoadingMore, - languagesCursor, - languageSearchTerm, - contentStatus, - exception, + countriesIsLoadingMore, + countriesCursor, + languages, + languagesHasMore, + languagesIsLoadingMore, + languagesCursor, + contentStatus, + exception, createdSource, ]; } From beec0e69af649f47a1bdfa7fa359d93feaaebc24 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:26:07 +0100 Subject: [PATCH 12/17] refactor(content_management): remove unused search event handlers - Remove CreateSourceCountrySearchChanged and CreateSourceLanguageSearchChanged event handlers - Remove associated transformer parameters from on event - Update _onLoadMoreCountriesRequested and _onLoadMoreLanguagesRequested to no longer filter based on search terms --- .../create_source/create_source_bloc.dart | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/lib/content_management/bloc/create_source/create_source_bloc.dart b/lib/content_management/bloc/create_source/create_source_bloc.dart index dda551ca..c2f2c88e 100644 --- a/lib/content_management/bloc/create_source/create_source_bloc.dart +++ b/lib/content_management/bloc/create_source/create_source_bloc.dart @@ -31,17 +31,9 @@ class CreateSourceBloc extends Bloc { on(_onHeadquartersChanged); on(_onStatusChanged); on(_onSubmitted); - on( - _onCountrySearchChanged, - transformer: droppable(), - ); on( _onLoadMoreCountriesRequested, ); - on( - _onLanguageSearchChanged, - transformer: droppable(), - ); on( _onLoadMoreLanguagesRequested, ); @@ -186,37 +178,6 @@ class CreateSourceBloc extends Bloc { } } - Future _onCountrySearchChanged( - CreateSourceCountrySearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(countrySearchTerm: event.searchTerm)); - try { - final countriesResponse = await _countriesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - countries: countriesResponse.items, - countriesCursor: countriesResponse.cursor, - countriesHasMore: countriesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: CreateSourceStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: CreateSourceStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreCountriesRequested( CreateSourceLoadMoreCountriesRequested event, Emitter emit, @@ -230,9 +191,6 @@ class CreateSourceBloc extends Bloc { pagination: state.countriesCursor != null ? PaginationOptions(cursor: state.countriesCursor) : null, - filter: state.countrySearchTerm.isNotEmpty - ? {'name': state.countrySearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); @@ -263,37 +221,6 @@ class CreateSourceBloc extends Bloc { } } - Future _onLanguageSearchChanged( - CreateSourceLanguageSearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(languageSearchTerm: event.searchTerm)); - try { - final languagesResponse = await _languagesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - languages: languagesResponse.items, - languagesCursor: languagesResponse.cursor, - languagesHasMore: languagesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: CreateSourceStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: CreateSourceStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreLanguagesRequested( CreateSourceLoadMoreLanguagesRequested event, Emitter emit, @@ -307,9 +234,6 @@ class CreateSourceBloc extends Bloc { pagination: state.languagesCursor != null ? PaginationOptions(cursor: state.languagesCursor) : null, - filter: state.languageSearchTerm.isNotEmpty - ? {'name': state.languageSearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); From b0b3e59a74a6f305f4938d0687d22152d6579840 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:27:29 +0100 Subject: [PATCH 13/17] refactor(content_management): replace SearchableDropdownFormField with DropdownButtonFormField - Replace SearchableDropdownFormField for language and headquarters selection with DropdownButtonFormField - Add support for loading more items in the dropdown menu - Improve UI by using a standard dropdown approach --- .../view/create_source_page.dart | 137 +++++++++--------- 1 file changed, 66 insertions(+), 71 deletions(-) diff --git a/lib/content_management/view/create_source_page.dart b/lib/content_management/view/create_source_page.dart index 82c921cf..d073d2a1 100644 --- a/lib/content_management/view/create_source_page.dart +++ b/lib/content_management/view/create_source_page.dart @@ -161,32 +161,34 @@ class _CreateSourceViewState extends State<_CreateSourceView> { .add(CreateSourceUrlChanged(value)), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.language, - bloc: context.read(), - initialValue: state.language, - itemsExtractor: (state) => state.languages, - hasMoreExtractor: (state) => state.languagesHasMore, - isLoadingExtractor: (state) => - state.status == CreateSourceStatus.loading, + DropdownButtonFormField( + value: state.language, + decoration: InputDecoration( + labelText: l10n.language, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.languages.map( + (language) => DropdownMenuItem( + value: language, + child: Text(language.name), + ), + ), + if (state.languagesHasMore) + DropdownMenuItem( + value: null, + child: const Center( + child: Text('Load More'), + ), + onTap: () => context.read().add( + const CreateSourceLoadMoreLanguagesRequested(), + ), + ), + ], onChanged: (value) => context .read() .add(CreateSourceLanguageChanged(value)), - onSearchChanged: (value) => context - .read() - .add(CreateSourceLanguageSearchChanged(value)), - onLoadMore: () => context.read().add( - const CreateSourceLoadMoreLanguagesRequested(), - ), - itemBuilder: (context, language) { - return ListTile( - title: Text(language.name), - ); - }, - selectedItemBuilder: (context, language) { - return Text(language.name); - }, ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField( @@ -209,57 +211,50 @@ class _CreateSourceViewState extends State<_CreateSourceView> { .add(CreateSourceTypeChanged(value)), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.headquarters, - bloc: context.read(), - initialValue: state.headquarters, - itemsExtractor: (state) => state.countries, - hasMoreExtractor: (state) => state.countriesHasMore, - isLoadingExtractor: (state) => - state.status == CreateSourceStatus.loading, - onChanged: (value) => context - .read() - .add(CreateSourceHeadquartersChanged(value)), - onSearchChanged: (value) => context - .read() - .add(CreateSourceCountrySearchChanged(value)), - onLoadMore: () => context.read().add( - const CreateSourceLoadMoreCountriesRequested(), - ), - itemBuilder: (context, country) { - return ListTile( - leading: SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), + DropdownButtonFormField( + value: state.headquarters, + decoration: InputDecoration( + labelText: l10n.headquarters, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.countries.map( + (country) => DropdownMenuItem( + value: country, + child: Row( + children: [ + SizedBox( + width: 32, + height: 20, + child: Image.network( + country.flagUrl, + fit: BoxFit.cover, + errorBuilder: + (context, error, stackTrace) => + const Icon(Icons.flag), + ), + ), + const SizedBox(width: AppSpacing.md), + Text(country.name), + ], ), ), - title: Text(country.name), - ); - }, - selectedItemBuilder: (context, country) { - return Row( - children: [ - SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), - ), + ), + if (state.countriesHasMore) + DropdownMenuItem( + value: null, + child: const Center( + child: Text('Load More'), ), - const SizedBox(width: AppSpacing.md), - Text(country.name), - ], - ); - }, + onTap: () => context.read().add( + const CreateSourceLoadMoreCountriesRequested(), + ), + ), + ], + onChanged: (value) => context + .read() + .add(CreateSourceHeadquartersChanged(value)), ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField( From 99d68fac1007597191df33e3506368614040a1cc Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:27:45 +0100 Subject: [PATCH 14/17] refactor(content_management): remove unused search change events - Remove EditSourceCountrySearchChanged and EditSourceLanguageSearchChanged events - These events were not being used in the bloc logic, likely because the UI already has direct access to the search text controllers --- .../bloc/edit_source/edit_source_event.dart | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/lib/content_management/bloc/edit_source/edit_source_event.dart b/lib/content_management/bloc/edit_source/edit_source_event.dart index b68ec430..ce576675 100644 --- a/lib/content_management/bloc/edit_source/edit_source_event.dart +++ b/lib/content_management/bloc/edit_source/edit_source_event.dart @@ -87,27 +87,11 @@ final class EditSourceSubmitted extends EditSourceEvent { const EditSourceSubmitted(); } -/// Event for when the country search term is changed. -final class EditSourceCountrySearchChanged extends EditSourceEvent { - const EditSourceCountrySearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more countries. final class EditSourceLoadMoreCountriesRequested extends EditSourceEvent { const EditSourceLoadMoreCountriesRequested(); } -/// Event for when the language search term is changed. -final class EditSourceLanguageSearchChanged extends EditSourceEvent { - const EditSourceLanguageSearchChanged(this.searchTerm); - final String searchTerm; - @override - List get props => [searchTerm]; -} - /// Event to request loading more languages. final class EditSourceLoadMoreLanguagesRequested extends EditSourceEvent { const EditSourceLoadMoreLanguagesRequested(); From 8f4e72aacb5ed4a53899f2470f92d392df5bfb03 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:28:57 +0100 Subject: [PATCH 15/17] refactor(content_management): remove country and language search terms - Remove countrySearchTerm and languageSearchTerm properties from EditSourceState - Update constructors and copyWith method to reflect the removal of these properties - Adjust the class to maintain functionality without search term tracking --- .../bloc/edit_source/edit_source_state.dart | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/content_management/bloc/edit_source/edit_source_state.dart b/lib/content_management/bloc/edit_source/edit_source_state.dart index 82dda1c0..c40b167d 100644 --- a/lib/content_management/bloc/edit_source/edit_source_state.dart +++ b/lib/content_management/bloc/edit_source/edit_source_state.dart @@ -33,12 +33,10 @@ final class EditSourceState extends Equatable { this.countriesHasMore = true, this.countriesIsLoadingMore = false, this.countriesCursor, - this.countrySearchTerm = '', this.languages = const [], this.languagesHasMore = true, this.languagesIsLoadingMore = false, this.languagesCursor, - this.languageSearchTerm = '', this.contentStatus = ContentStatus.active, this.exception, this.updatedSource, @@ -56,12 +54,10 @@ final class EditSourceState extends Equatable { final bool countriesHasMore; final bool countriesIsLoadingMore; final String? countriesCursor; - final String countrySearchTerm; final List languages; final bool languagesHasMore; final bool languagesIsLoadingMore; final String? languagesCursor; - final String languageSearchTerm; final ContentStatus contentStatus; final HttpException? exception; final Source? updatedSource; @@ -88,12 +84,10 @@ final class EditSourceState extends Equatable { bool? countriesHasMore, bool? countriesIsLoadingMore, String? countriesCursor, - String? countrySearchTerm, List? languages, bool? languagesHasMore, bool? languagesIsLoadingMore, String? languagesCursor, - String? languageSearchTerm, ContentStatus? contentStatus, HttpException? exception, Source? updatedSource, @@ -112,13 +106,11 @@ final class EditSourceState extends Equatable { countriesIsLoadingMore: countriesIsLoadingMore ?? this.countriesIsLoadingMore, countriesCursor: countriesCursor ?? this.countriesCursor, - countrySearchTerm: countrySearchTerm ?? this.countrySearchTerm, languages: languages ?? this.languages, languagesHasMore: languagesHasMore ?? this.languagesHasMore, languagesIsLoadingMore: languagesIsLoadingMore ?? this.languagesIsLoadingMore, languagesCursor: languagesCursor ?? this.languagesCursor, - languageSearchTerm: languageSearchTerm ?? this.languageSearchTerm, contentStatus: contentStatus ?? this.contentStatus, exception: exception, updatedSource: updatedSource ?? this.updatedSource, @@ -139,12 +131,10 @@ final class EditSourceState extends Equatable { countriesHasMore, countriesIsLoadingMore, countriesCursor, - countrySearchTerm, languages, languagesHasMore, languagesIsLoadingMore, languagesCursor, - languageSearchTerm, contentStatus, exception, updatedSource, From a743aec60651e105732876dd1560ebec8b81c492 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:30:04 +0100 Subject: [PATCH 16/17] refactor(content_management): remove unused search event handlers - Remove EditSourceCountrySearchChanged and EditSourceLanguageSearchChanged event handlers - Remove related code from EditSourceBloc constructor - Remove droppable() transformer usage - Adjust load more countries/languages functions to no longer filter based on search term --- .../bloc/edit_source/edit_source_bloc.dart | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/lib/content_management/bloc/edit_source/edit_source_bloc.dart b/lib/content_management/bloc/edit_source/edit_source_bloc.dart index 5f886a04..a503235b 100644 --- a/lib/content_management/bloc/edit_source/edit_source_bloc.dart +++ b/lib/content_management/bloc/edit_source/edit_source_bloc.dart @@ -32,17 +32,9 @@ class EditSourceBloc extends Bloc { on(_onHeadquartersChanged); on(_onStatusChanged); on(_onSubmitted); - on( - _onCountrySearchChanged, - transformer: droppable(), - ); on( _onLoadMoreCountriesRequested, ); - on( - _onLanguageSearchChanged, - transformer: droppable(), - ); on( _onLoadMoreLanguagesRequested, ); @@ -240,37 +232,6 @@ class EditSourceBloc extends Bloc { } } - Future _onCountrySearchChanged( - EditSourceCountrySearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(countrySearchTerm: event.searchTerm)); - try { - final countriesResponse = await _countriesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - countries: countriesResponse.items, - countriesCursor: countriesResponse.cursor, - countriesHasMore: countriesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: EditSourceStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: EditSourceStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreCountriesRequested( EditSourceLoadMoreCountriesRequested event, Emitter emit, @@ -284,9 +245,6 @@ class EditSourceBloc extends Bloc { pagination: state.countriesCursor != null ? PaginationOptions(cursor: state.countriesCursor) : null, - filter: state.countrySearchTerm.isNotEmpty - ? {'name': state.countrySearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); @@ -317,37 +275,6 @@ class EditSourceBloc extends Bloc { } } - Future _onLanguageSearchChanged( - EditSourceLanguageSearchChanged event, - Emitter emit, - ) async { - await Future.delayed(_searchDebounceDuration); - emit(state.copyWith(languageSearchTerm: event.searchTerm)); - try { - final languagesResponse = await _languagesRepository.readAll( - filter: event.searchTerm.isNotEmpty ? {'name': event.searchTerm} : null, - sort: [const SortOption('name', SortOrder.asc)], - ); - - emit( - state.copyWith( - languages: languagesResponse.items, - languagesCursor: languagesResponse.cursor, - languagesHasMore: languagesResponse.hasMore, - ), - ); - } on HttpException catch (e) { - emit(state.copyWith(status: EditSourceStatus.failure, exception: e)); - } catch (e) { - emit( - state.copyWith( - status: EditSourceStatus.failure, - exception: UnknownException('An unexpected error occurred: $e'), - ), - ); - } - } - Future _onLoadMoreLanguagesRequested( EditSourceLoadMoreLanguagesRequested event, Emitter emit, @@ -361,9 +288,6 @@ class EditSourceBloc extends Bloc { pagination: state.languagesCursor != null ? PaginationOptions(cursor: state.languagesCursor) : null, - filter: state.languageSearchTerm.isNotEmpty - ? {'name': state.languageSearchTerm} - : null, sort: [const SortOption('name', SortOrder.asc)], ); From d34651f8702904c015aaba94ed6efcc1b9e3b585 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 1 Aug 2025 08:31:11 +0100 Subject: [PATCH 17/17] refactor(content_management): replace SearchableDropdownFormField with DropdownButtonFormField - Replace SearchableDropdownFormField with DropdownButtonFormField for language and headquarters selection - Add support for loading more items in the dropdown - Improve UI by using standard DropdownMenuItem widgets - Simplify item builder logic for better readability and maintainability --- .../view/edit_source_page.dart | 137 +++++++++--------- 1 file changed, 66 insertions(+), 71 deletions(-) diff --git a/lib/content_management/view/edit_source_page.dart b/lib/content_management/view/edit_source_page.dart index 22529b32..c050df9c 100644 --- a/lib/content_management/view/edit_source_page.dart +++ b/lib/content_management/view/edit_source_page.dart @@ -191,32 +191,34 @@ class _EditSourceViewState extends State<_EditSourceView> { ), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.language, - bloc: context.read(), - initialValue: state.language, - itemsExtractor: (state) => state.languages, - hasMoreExtractor: (state) => state.languagesHasMore, - isLoadingExtractor: (state) => - state.status == EditSourceStatus.loading, + DropdownButtonFormField( + value: state.language, + decoration: InputDecoration( + labelText: l10n.language, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.languages.map( + (language) => DropdownMenuItem( + value: language, + child: Text(language.name), + ), + ), + if (state.languagesHasMore) + DropdownMenuItem( + value: null, + child: const Center( + child: Text('Load More'), + ), + onTap: () => context.read().add( + const EditSourceLoadMoreLanguagesRequested(), + ), + ), + ], onChanged: (value) => context .read() .add(EditSourceLanguageChanged(value)), - onSearchChanged: (value) => context - .read() - .add(EditSourceLanguageSearchChanged(value)), - onLoadMore: () => context.read().add( - const EditSourceLoadMoreLanguagesRequested(), - ), - itemBuilder: (context, language) { - return ListTile( - title: Text(language.name), - ); - }, - selectedItemBuilder: (context, language) { - return Text(language.name); - }, ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField( @@ -239,57 +241,50 @@ class _EditSourceViewState extends State<_EditSourceView> { ), ), const SizedBox(height: AppSpacing.lg), - SearchableDropdownFormField( - labelText: l10n.headquarters, - bloc: context.read(), - initialValue: state.headquarters, - itemsExtractor: (state) => state.countries, - hasMoreExtractor: (state) => state.countriesHasMore, - isLoadingExtractor: (state) => - state.status == EditSourceStatus.loading, - onChanged: (value) => context - .read() - .add(EditSourceHeadquartersChanged(value)), - onSearchChanged: (value) => context - .read() - .add(EditSourceCountrySearchChanged(value)), - onLoadMore: () => context.read().add( - const EditSourceLoadMoreCountriesRequested(), - ), - itemBuilder: (context, country) { - return ListTile( - leading: SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), + DropdownButtonFormField( + value: state.headquarters, + decoration: InputDecoration( + labelText: l10n.headquarters, + border: const OutlineInputBorder(), + ), + items: [ + DropdownMenuItem(value: null, child: Text(l10n.none)), + ...state.countries.map( + (country) => DropdownMenuItem( + value: country, + child: Row( + children: [ + SizedBox( + width: 32, + height: 20, + child: Image.network( + country.flagUrl, + fit: BoxFit.cover, + errorBuilder: + (context, error, stackTrace) => + const Icon(Icons.flag), + ), + ), + const SizedBox(width: AppSpacing.md), + Text(country.name), + ], ), ), - title: Text(country.name), - ); - }, - selectedItemBuilder: (context, country) { - return Row( - children: [ - SizedBox( - width: 32, - height: 20, - child: Image.network( - country.flagUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => - const Icon(Icons.flag), - ), + ), + if (state.countriesHasMore) + DropdownMenuItem( + value: null, + child: const Center( + child: Text('Load More'), ), - const SizedBox(width: AppSpacing.md), - Text(country.name), - ], - ); - }, + onTap: () => context.read().add( + const EditSourceLoadMoreCountriesRequested(), + ), + ), + ], + onChanged: (value) => context + .read() + .add(EditSourceHeadquartersChanged(value)), ), const SizedBox(height: AppSpacing.lg), DropdownButtonFormField(