Skip to content

Fix duplicate table entry #20

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
merged 5 commits into from
Jul 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
115 changes: 38 additions & 77 deletions lib/content_management/bloc/content_management_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@ class ContentManagementBloc
super(const ContentManagementState()) {
on<ContentManagementTabChanged>(_onContentManagementTabChanged);
on<LoadHeadlinesRequested>(_onLoadHeadlinesRequested);
on<HeadlineAdded>(_onHeadlineAdded);
on<HeadlineUpdated>(_onHeadlineUpdated);
on<DeleteHeadlineRequested>(_onDeleteHeadlineRequested);
on<LoadCategoriesRequested>(_onLoadCategoriesRequested);
on<CategoryAdded>(_onCategoryAdded);
on<CategoryUpdated>(_onCategoryUpdated);
on<DeleteCategoryRequested>(_onDeleteCategoryRequested);
on<LoadSourcesRequested>(_onLoadSourcesRequested);
on<SourceAdded>(_onSourceAdded);
on<SourceUpdated>(_onSourceUpdated);
on<DeleteSourceRequested>(_onOnDeleteSourceRequested);
}
Expand Down Expand Up @@ -92,31 +89,6 @@ class ContentManagementBloc
}
}

void _onHeadlineAdded(
HeadlineAdded event,
Emitter<ContentManagementState> emit,
) {
final updatedHeadlines = [event.headline, ...state.headlines];
emit(
state.copyWith(
headlines: updatedHeadlines,
headlinesStatus: ContentManagementStatus.success,
),
);
}

void _onHeadlineUpdated(
HeadlineUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedHeadlines = List<Headline>.from(state.headlines);
final index = updatedHeadlines.indexWhere((h) => h.id == event.headline.id);
if (index != -1) {
updatedHeadlines[index] = event.headline;
emit(state.copyWith(headlines: updatedHeadlines));
}
}

Future<void> _onDeleteHeadlineRequested(
DeleteHeadlineRequested event,
Emitter<ContentManagementState> emit,
Expand Down Expand Up @@ -144,6 +116,18 @@ class ContentManagementBloc
}
}

void _onHeadlineUpdated(
HeadlineUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedHeadlines = List<Headline>.from(state.headlines);
final index = updatedHeadlines.indexWhere((h) => h.id == event.headline.id);
if (index != -1) {
updatedHeadlines[index] = event.headline;
emit(state.copyWith(headlines: updatedHeadlines));
}
}

Future<void> _onLoadCategoriesRequested(
LoadCategoriesRequested event,
Emitter<ContentManagementState> emit,
Expand Down Expand Up @@ -182,33 +166,6 @@ class ContentManagementBloc
}
}

void _onCategoryAdded(
CategoryAdded event,
Emitter<ContentManagementState> emit,
) {
final updatedCategories = [event.category, ...state.categories];
emit(
state.copyWith(
categories: updatedCategories,
categoriesStatus: ContentManagementStatus.success,
),
);
}

void _onCategoryUpdated(
CategoryUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedCategories = List<Category>.from(state.categories);
final index = updatedCategories.indexWhere(
(c) => c.id == event.category.id,
);
if (index != -1) {
updatedCategories[index] = event.category;
emit(state.copyWith(categories: updatedCategories));
}
}

Future<void> _onDeleteCategoryRequested(
DeleteCategoryRequested event,
Emitter<ContentManagementState> emit,
Expand Down Expand Up @@ -236,6 +193,20 @@ class ContentManagementBloc
}
}

void _onCategoryUpdated(
CategoryUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedCategories = List<Category>.from(state.categories);
final index = updatedCategories.indexWhere(
(c) => c.id == event.category.id,
);
if (index != -1) {
updatedCategories[index] = event.category;
emit(state.copyWith(categories: updatedCategories));
}
}

Future<void> _onLoadSourcesRequested(
LoadSourcesRequested event,
Emitter<ContentManagementState> emit,
Expand Down Expand Up @@ -274,28 +245,6 @@ class ContentManagementBloc
}
}

void _onSourceAdded(SourceAdded event, Emitter<ContentManagementState> emit) {
final updatedSources = [event.source, ...state.sources];
emit(
state.copyWith(
sources: updatedSources,
sourcesStatus: ContentManagementStatus.success,
),
);
}

void _onSourceUpdated(
SourceUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedSources = List<Source>.from(state.sources);
final index = updatedSources.indexWhere((s) => s.id == event.source.id);
if (index != -1) {
updatedSources[index] = event.source;
emit(state.copyWith(sources: updatedSources));
}
}

Future<void> _onOnDeleteSourceRequested(
DeleteSourceRequested event,
Emitter<ContentManagementState> emit,
Expand All @@ -322,4 +271,16 @@ class ContentManagementBloc
);
}
}

void _onSourceUpdated(
SourceUpdated event,
Emitter<ContentManagementState> emit,
) {
final updatedSources = List<Source>.from(state.sources);
final index = updatedSources.indexWhere((s) => s.id == event.source.id);
if (index != -1) {
updatedSources[index] = event.source;
emit(state.copyWith(sources: updatedSources));
}
}
}
90 changes: 24 additions & 66 deletions lib/content_management/bloc/content_management_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ final class LoadHeadlinesRequested extends ContentManagementEvent {
List<Object?> get props => [startAfterId, limit];
}

/// {@template headline_added}
/// Event to add a new headline to the local state.
/// {@template delete_headline_requested}
/// Event to request deletion of a headline.
/// {@endtemplate}
final class HeadlineAdded extends ContentManagementEvent {
/// {@macro headline_added}
const HeadlineAdded(this.headline);
final class DeleteHeadlineRequested extends ContentManagementEvent {
/// {@macro delete_headline_requested}
const DeleteHeadlineRequested(this.id);

/// The headline that was added.
final Headline headline;
/// The ID of the headline to delete.
final String id;

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

/// {@template headline_updated}
Expand All @@ -66,20 +66,6 @@ final class HeadlineUpdated extends ContentManagementEvent {
List<Object?> get props => [headline];
}

/// {@template delete_headline_requested}
/// Event to request deletion of a headline.
/// {@endtemplate}
final class DeleteHeadlineRequested extends ContentManagementEvent {
/// {@macro delete_headline_requested}
const DeleteHeadlineRequested(this.id);

/// The ID of the headline to delete.
final String id;

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

/// {@template load_categories_requested}
/// Event to request loading of categories.
/// {@endtemplate}
Expand All @@ -97,18 +83,18 @@ final class LoadCategoriesRequested extends ContentManagementEvent {
List<Object?> get props => [startAfterId, limit];
}

/// {@template category_added}
/// Event to add a new category to the local state.
/// {@template delete_category_requested}
/// Event to request deletion of a category.
/// {@endtemplate}
final class CategoryAdded extends ContentManagementEvent {
/// {@macro category_added}
const CategoryAdded(this.category);
final class DeleteCategoryRequested extends ContentManagementEvent {
/// {@macro delete_category_requested}
const DeleteCategoryRequested(this.id);

/// The category that was added.
final Category category;
/// The ID of the category to delete.
final String id;

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

/// {@template category_updated}
Expand All @@ -125,20 +111,6 @@ final class CategoryUpdated extends ContentManagementEvent {
List<Object?> get props => [category];
}

/// {@template delete_category_requested}
/// Event to request deletion of a category.
/// {@endtemplate}
final class DeleteCategoryRequested extends ContentManagementEvent {
/// {@macro delete_category_requested}
const DeleteCategoryRequested(this.id);

/// The ID of the category to delete.
final String id;

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

/// {@template load_sources_requested}
/// Event to request loading of sources.
/// {@endtemplate}
Expand All @@ -156,18 +128,18 @@ final class LoadSourcesRequested extends ContentManagementEvent {
List<Object?> get props => [startAfterId, limit];
}

/// {@template source_added}
/// Event to add a new source to the local state.
/// {@template delete_source_requested}
/// Event to request deletion of a source.
/// {@endtemplate}
final class SourceAdded extends ContentManagementEvent {
/// {@macro source_added}
const SourceAdded(this.source);
final class DeleteSourceRequested extends ContentManagementEvent {
/// {@macro delete_source_requested}
const DeleteSourceRequested(this.id);

/// The source that was added.
final Source source;
/// The ID of the source to delete.
final String id;

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

/// {@template source_updated}
Expand All @@ -183,17 +155,3 @@ final class SourceUpdated extends ContentManagementEvent {
@override
List<Object?> get props => [source];
}

/// {@template delete_source_requested}
/// Event to request deletion of a source.
/// {@endtemplate}
final class DeleteSourceRequested extends ContentManagementEvent {
/// {@macro delete_source_requested}
const DeleteSourceRequested(this.id);

/// The ID of the source to delete.
final String id;

@override
List<Object?> get props => [id];
}
4 changes: 3 additions & 1 deletion lib/content_management/view/create_category_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:ht_dashboard/content_management/bloc/content_management_bloc.dart';
import 'package:ht_dashboard/content_management/bloc/create_category/create_category_bloc.dart';
import 'package:ht_dashboard/l10n/l10n.dart';
import 'package:ht_dashboard/shared/constants/pagination_constants.dart';
import 'package:ht_dashboard/shared/shared.dart';
import 'package:ht_data_repository/ht_data_repository.dart';
import 'package:ht_shared/ht_shared.dart';
Expand Down Expand Up @@ -81,7 +82,8 @@ class _CreateCategoryViewState extends State<_CreateCategoryView> {
SnackBar(content: Text(l10n.categoryCreatedSuccessfully)),
);
context.read<ContentManagementBloc>().add(
CategoryAdded(state.createdCategory!),
// Refresh the list to show the new category
const LoadCategoriesRequested(limit: kDefaultRowsPerPage),
);
Comment on lines 84 to 87

Choose a reason for hiding this comment

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

medium

The code now reloads the categories after creating a new one. While this fixes the duplicate entry issue, it might not be the most efficient approach. Consider updating the local state directly with the new category if the API returns the created category object.

context.pop();
}
Expand Down
4 changes: 3 additions & 1 deletion lib/content_management/view/create_headline_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:ht_dashboard/content_management/bloc/content_management_bloc.dart';
import 'package:ht_dashboard/content_management/bloc/create_headline/create_headline_bloc.dart';
import 'package:ht_dashboard/l10n/l10n.dart';
import 'package:ht_dashboard/shared/constants/pagination_constants.dart';
import 'package:ht_dashboard/shared/shared.dart';
import 'package:ht_data_repository/ht_data_repository.dart';
import 'package:ht_shared/ht_shared.dart';
Expand Down Expand Up @@ -83,7 +84,8 @@ class _CreateHeadlineViewState extends State<_CreateHeadlineView> {
SnackBar(content: Text(l10n.headlineCreatedSuccessfully)),
);
context.read<ContentManagementBloc>().add(
HeadlineAdded(state.createdHeadline!),
// Refresh the list to show the new headline
const LoadHeadlinesRequested(limit: kDefaultRowsPerPage),
);
Comment on lines 86 to 89

Choose a reason for hiding this comment

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

medium

The code now reloads the headlines after creating a new one. While this fixes the duplicate entry issue, it might not be the most efficient approach. Consider updating the local state directly with the new headline if the API returns the created headline object.

context.pop();
}
Expand Down
4 changes: 3 additions & 1 deletion lib/content_management/view/create_source_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:ht_dashboard/content_management/bloc/content_management_bloc.dar
import 'package:ht_dashboard/content_management/bloc/create_source/create_source_bloc.dart';
import 'package:ht_dashboard/content_management/bloc/edit_source/edit_source_bloc.dart';
import 'package:ht_dashboard/l10n/l10n.dart';
import 'package:ht_dashboard/shared/constants/pagination_constants.dart';
import 'package:ht_dashboard/shared/shared.dart';
import 'package:ht_data_repository/ht_data_repository.dart';
import 'package:ht_shared/ht_shared.dart';
Expand Down Expand Up @@ -83,7 +84,8 @@ class _CreateSourceViewState extends State<_CreateSourceView> {
SnackBar(content: Text(l10n.sourceCreatedSuccessfully)),
);
context.read<ContentManagementBloc>().add(
SourceAdded(state.createdSource!),
// Refresh the list to show the new source
const LoadSourcesRequested(limit: kDefaultRowsPerPage),
);
Comment on lines 86 to 89

Choose a reason for hiding this comment

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

medium

The code now reloads the sources after creating a new one. While this fixes the duplicate entry issue, it might not be the most efficient approach. Consider updating the local state directly with the new source if the API returns the created source object.

context.pop();
}
Expand Down
Loading