Skip to content

Refactor add content lifecyle management for the content management feature #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
901627f
chore(dependencies): update go_router to version 16.0.0 and device_fr…
fulleni Jul 3, 2025
b3f2118
feat(bloc-observer): add print statements for onChange and onError lo…
fulleni Jul 3, 2025
3fd6859
refactor: This first step isolates the change to the CreateCategorySt…
fulleni Jul 3, 2025
c0d4824
refactor: This step introduces the CreateCategoryStatusChanged event,…
fulleni Jul 3, 2025
be16c56
refactor: updates the CreateCategoryBloc to handle the new CreateCate…
fulleni Jul 3, 2025
1ea810d
feat: adds the DropdownButtonFormField to the CreateCategoryPage UI. …
fulleni Jul 3, 2025
173670f
refactor: updates the EditCategoryState to manage the ContentStatus o…
fulleni Jul 3, 2025
4d158ab
feat: introduces the EditCategoryStatusChanged event. This is necessa…
fulleni Jul 3, 2025
f8b07a6
feat: updates the EditCategoryBloc to fully manage the ContentStatus.…
fulleni Jul 3, 2025
8404bb8
feat: adds the DropdownButtonFormField to the EditCategoryPage UI. Th…
fulleni Jul 3, 2025
0f0a79c
refactor: updates the CategoriesPage data table to display the most r…
fulleni Jul 3, 2025
e451e73
feat: modifies the existing CreateSourceState to include the contentS…
fulleni Jul 3, 2025
b6d327a
feature: adds the CreateSourceStatusChanged event to the create_sourc…
fulleni Jul 3, 2025
a080a68
feat: updates the CreateSourceBloc to handle the new CreateSourceStat…
fulleni Jul 3, 2025
6ef5246
feat: adds the DropdownButtonFormField to the CreateSourcePage UI, a…
fulleni Jul 3, 2025
6816216
feat: modifies the EditSourceState to include the contentStatus field…
fulleni Jul 3, 2025
325b519
feat: adds the EditSourceStatusChanged event to the edit_source_event…
fulleni Jul 3, 2025
2da7da7
feat: updates the EditSourceBloc to fully manage the ContentStatus. T…
fulleni Jul 3, 2025
2384e50
feat: updates the EditSourceBloc to fully manage the ContentStatus. T…
fulleni Jul 3, 2025
74afe79
feat: updates the SourcesPage data table to display the most relevant…
fulleni Jul 3, 2025
6d9740c
feat: modifies the CreateHeadlineState to include the contentStatus f…
fulleni Jul 3, 2025
f78983e
feat: adds the CreateHeadlineStatusChanged event to the create_headli…
fulleni Jul 3, 2025
57ede75
feat: updates the CreateHeadlineBloc to handle the new CreateHeadline…
fulleni Jul 3, 2025
3d4016e
feat: adds the DropdownButtonFormField for ContentStatus to the Creat…
fulleni Jul 3, 2025
75bb6de
feat: modifies the EditHeadlineState to include the contentStatus fie…
fulleni Jul 3, 2025
de0bbba
feat: introduces the EditHeadlineStatusChanged event, which is necess…
fulleni Jul 3, 2025
73e116f
feat: updates the EditHeadlineBloc to fully manage the ContentStatus.…
fulleni Jul 3, 2025
52be023
feat: adds the DropdownButtonFormField for ContentStatus to the Edit…
fulleni Jul 3, 2025
834b2ac
feat: adds the DropdownButtonFormField for ContentStatus to the Edit…
fulleni Jul 3, 2025
ae5554a
feat: creates a new extension on the ContentStatus enum. This extensi…
fulleni Jul 3, 2025
6edae50
feat: adds the required keys and their translations to the English an…
fulleni Jul 3, 2025
f29fae5
refactor: updates the ContentStatusL10n extension to use the actual l…
fulleni Jul 3, 2025
ce656a5
feat: integrates the localization extension into the CreateCategoryPa…
fulleni Jul 3, 2025
ef53b5e
refactor: integrates the localization extension into the EditCategory…
fulleni Jul 3, 2025
7f7a37a
feat: integrates the localization extension into the CreateSourcePage…
fulleni Jul 3, 2025
50a0fe3
refactor: integrates the localization extension into the EditSourcePa…
fulleni Jul 3, 2025
c84fb40
refactor: integrates the localization extension into the SourcesPage …
fulleni Jul 3, 2025
b8b00e5
refactor: integrates the localization extension into the CreateHeadli…
fulleni Jul 3, 2025
7532207
refactor: integrates the localization extension into the EditHeadlin…
fulleni Jul 3, 2025
ae7d7ba
refactor: integrates the localization extension into the HeadlinesPag…
fulleni Jul 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/bloc_observer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class AppBlocObserver extends BlocObserver {
void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
super.onChange(bloc, change);
log('onChange(${bloc.runtimeType}, $change)');
print('onChange(${bloc.runtimeType}, $change)');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Remove this print() statement to avoid cluttering production logs. The log() call on the previous line is sufficient.

}

@override
void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
log('onError(${bloc.runtimeType}, $error, $stackTrace)');
print('onError(${bloc.runtimeType}, $error, $stackTrace)');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Remove this print() statement to avoid cluttering production logs. The log() call on the previous line is sufficient.

super.onError(bloc, error, stackTrace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class CreateCategoryBloc
on<CreateCategoryNameChanged>(_onNameChanged);
on<CreateCategoryDescriptionChanged>(_onDescriptionChanged);
on<CreateCategoryIconUrlChanged>(_onIconUrlChanged);
on<CreateCategoryStatusChanged>(_onStatusChanged);
on<CreateCategorySubmitted>(_onSubmitted);
}

Expand Down Expand Up @@ -58,6 +59,18 @@ class CreateCategoryBloc
);
}

void _onStatusChanged(
CreateCategoryStatusChanged event,
Emitter<CreateCategoryState> emit,
) {
emit(
state.copyWith(
contentStatus: event.status,
status: CreateCategoryStatus.initial,
),
);
}

Future<void> _onSubmitted(
CreateCategorySubmitted event,
Emitter<CreateCategoryState> emit,
Expand All @@ -70,6 +83,7 @@ class CreateCategoryBloc
name: state.name,
description: state.description.isNotEmpty ? state.description : null,
iconUrl: state.iconUrl.isNotEmpty ? state.iconUrl : null,
status: state.contentStatus,
);

await _categoriesRepository.create(item: newCategory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,40 @@ sealed class CreateCategoryEvent extends Equatable {
const CreateCategoryEvent();

@override
List<Object> get props => [];
List<Object?> get props => [];
}

/// Event for when the category's name is changed.
final class CreateCategoryNameChanged extends CreateCategoryEvent {
const CreateCategoryNameChanged(this.name);
final String name;
@override
List<Object> get props => [name];
List<Object?> get props => [name];
}

/// Event for when the category's description is changed.
final class CreateCategoryDescriptionChanged extends CreateCategoryEvent {
const CreateCategoryDescriptionChanged(this.description);
final String description;
@override
List<Object> get props => [description];
List<Object?> get props => [description];
}

/// Event for when the category's icon URL is changed.
final class CreateCategoryIconUrlChanged extends CreateCategoryEvent {
const CreateCategoryIconUrlChanged(this.iconUrl);
final String iconUrl;
@override
List<Object> get props => [iconUrl];
List<Object?> get props => [iconUrl];
}

/// Event for when the category's status is changed.
final class CreateCategoryStatusChanged extends CreateCategoryEvent {
const CreateCategoryStatusChanged(this.status);

final ContentStatus status;
@override
List<Object?> get props => [status];
}

/// Event to signal that the form should be submitted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ final class CreateCategoryState extends Equatable {
this.name = '',
this.description = '',
this.iconUrl = '',
this.contentStatus = ContentStatus.active,
this.errorMessage,
});

final CreateCategoryStatus status;
final String name;
final String description;
final String iconUrl;
final ContentStatus contentStatus;
final String? errorMessage;

/// Returns true if the form is valid and can be submitted.
Expand All @@ -41,17 +43,26 @@ final class CreateCategoryState extends Equatable {
String? name,
String? description,
String? iconUrl,
ContentStatus? contentStatus,
String? errorMessage,
}) {
return CreateCategoryState(
status: status ?? this.status,
name: name ?? this.name,
description: description ?? this.description,
iconUrl: iconUrl ?? this.iconUrl,
contentStatus: contentStatus ?? this.contentStatus,
errorMessage: errorMessage,
);
}

@override
List<Object?> get props => [status, name, description, iconUrl, errorMessage];
List<Object?> get props => [
status,
name,
description,
iconUrl,
contentStatus,
errorMessage,
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CreateHeadlineBloc
on<CreateHeadlineImageUrlChanged>(_onImageUrlChanged);
on<CreateHeadlineSourceChanged>(_onSourceChanged);
on<CreateHeadlineCategoryChanged>(_onCategoryChanged);
on<CreateHeadlineStatusChanged>(_onStatusChanged);
on<CreateHeadlineSubmitted>(_onSubmitted);
}

Expand Down Expand Up @@ -114,6 +115,18 @@ class CreateHeadlineBloc
emit(state.copyWith(category: () => event.category));
}

void _onStatusChanged(
CreateHeadlineStatusChanged event,
Emitter<CreateHeadlineState> emit,
) {
emit(
state.copyWith(
contentStatus: event.status,
status: CreateHeadlineStatus.initial,
),
);
}

Future<void> _onSubmitted(
CreateHeadlineSubmitted event,
Emitter<CreateHeadlineState> emit,
Expand All @@ -129,6 +142,7 @@ class CreateHeadlineBloc
imageUrl: state.imageUrl.isNotEmpty ? state.imageUrl : null,
source: state.source,
category: state.category,
status: state.contentStatus,
);

await _headlinesRepository.create(item: newHeadline);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,68 +1,77 @@
part of 'create_headline_bloc.dart';

/// Base class for all events related to the [CreateHeadlineBloc].
abstract class CreateHeadlineEvent extends Equatable {
sealed class CreateHeadlineEvent extends Equatable {
const CreateHeadlineEvent();

@override
List<Object?> get props => [];
}

/// Event to signal that the data for dropdowns should be loaded.
class CreateHeadlineDataLoaded extends CreateHeadlineEvent {
final class CreateHeadlineDataLoaded extends CreateHeadlineEvent {
const CreateHeadlineDataLoaded();
}

/// Event for when the headline's title is changed.
class CreateHeadlineTitleChanged extends CreateHeadlineEvent {
final class CreateHeadlineTitleChanged extends CreateHeadlineEvent {
const CreateHeadlineTitleChanged(this.title);
final String title;
@override
List<Object> get props => [title];
List<Object?> get props => [title];
}

/// Event for when the headline's description is changed.
class CreateHeadlineDescriptionChanged extends CreateHeadlineEvent {
final class CreateHeadlineDescriptionChanged extends CreateHeadlineEvent {
const CreateHeadlineDescriptionChanged(this.description);
final String description;
@override
List<Object> get props => [description];
List<Object?> get props => [description];
}

/// Event for when the headline's URL is changed.
class CreateHeadlineUrlChanged extends CreateHeadlineEvent {
final class CreateHeadlineUrlChanged extends CreateHeadlineEvent {
const CreateHeadlineUrlChanged(this.url);
final String url;
@override
List<Object> get props => [url];
List<Object?> get props => [url];
}

/// Event for when the headline's image URL is changed.
class CreateHeadlineImageUrlChanged extends CreateHeadlineEvent {
final class CreateHeadlineImageUrlChanged extends CreateHeadlineEvent {
const CreateHeadlineImageUrlChanged(this.imageUrl);
final String imageUrl;
@override
List<Object> get props => [imageUrl];
List<Object?> get props => [imageUrl];
}

/// Event for when the headline's source is changed.
class CreateHeadlineSourceChanged extends CreateHeadlineEvent {
final class CreateHeadlineSourceChanged extends CreateHeadlineEvent {
const CreateHeadlineSourceChanged(this.source);
final Source? source;
@override
List<Object?> get props => [source];
}

/// Event for when the headline's category is changed.
class CreateHeadlineCategoryChanged extends CreateHeadlineEvent {
final class CreateHeadlineCategoryChanged extends CreateHeadlineEvent {
const CreateHeadlineCategoryChanged(this.category);
final Category? category;
@override
List<Object?> get props => [category];
}

/// Event for when the headline's status is changed.
final class CreateHeadlineStatusChanged extends CreateHeadlineEvent {
const CreateHeadlineStatusChanged(this.status);

final ContentStatus status;

@override
List<Object?> get props => [status];
}

/// Event to signal that the form should be submitted.
class CreateHeadlineSubmitted extends CreateHeadlineEvent {
final class CreateHeadlineSubmitted extends CreateHeadlineEvent {
const CreateHeadlineSubmitted();
}

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ final class CreateHeadlineState extends Equatable {
this.category,
this.sources = const [],
this.categories = const [],
this.contentStatus = ContentStatus.active,
this.errorMessage,
});

Expand All @@ -42,6 +43,7 @@ final class CreateHeadlineState extends Equatable {
final Category? category;
final List<Source> sources;
final List<Category> categories;
final ContentStatus contentStatus;
final String? errorMessage;

/// Returns true if the form is valid and can be submitted.
Expand All @@ -57,6 +59,7 @@ final class CreateHeadlineState extends Equatable {
ValueGetter<Category?>? category,
List<Source>? sources,
List<Category>? categories,
ContentStatus? contentStatus,
String? errorMessage,
}) {
return CreateHeadlineState(
Expand All @@ -69,22 +72,23 @@ final class CreateHeadlineState extends Equatable {
category: category != null ? category() : this.category,
sources: sources ?? this.sources,
categories: categories ?? this.categories,
contentStatus: contentStatus ?? this.contentStatus,
errorMessage: errorMessage ?? this.errorMessage,
);
}

@override
List<Object?> get props => [
status,
title,
description,
url,
imageUrl,
source,
category,
sources,
categories,
errorMessage,
];
status,
title,
description,
url,
imageUrl,
source,
category,
sources,
categories,
contentStatus,
errorMessage,
];
}

14 changes: 14 additions & 0 deletions lib/content_management/bloc/create_source/create_source_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
on<CreateSourceTypeChanged>(_onSourceTypeChanged);
on<CreateSourceLanguageChanged>(_onLanguageChanged);
on<CreateSourceHeadquartersChanged>(_onHeadquartersChanged);
on<CreateSourceStatusChanged>(_onStatusChanged);
on<CreateSourceSubmitted>(_onSubmitted);
}

Expand Down Expand Up @@ -103,6 +104,18 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
emit(state.copyWith(headquarters: () => event.headquarters));
}

void _onStatusChanged(
CreateSourceStatusChanged event,
Emitter<CreateSourceState> emit,
) {
emit(
state.copyWith(
contentStatus: event.status,
status: CreateSourceStatus.initial,
),
);
}

Future<void> _onSubmitted(
CreateSourceSubmitted event,
Emitter<CreateSourceState> emit,
Expand All @@ -118,6 +131,7 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
sourceType: state.sourceType,
language: state.language.isNotEmpty ? state.language : null,
headquarters: state.headquarters,
status: state.contentStatus,
);

await _sourcesRepository.create(item: newSource);
Expand Down
Loading
Loading