Skip to content

Commit 3436a24

Browse files
committed
feat(content): add edit category bloc
- Implemented edit category logic - Added state management with bloc - Handles loading, updates, submission
1 parent 7b4a99a commit 3436a24

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import 'package:bloc/bloc.dart';
2+
import 'package:equatable/equatable.dart';
3+
import 'package:ht_data_repository/ht_data_repository.dart';
4+
import 'package:ht_shared/ht_shared.dart';
5+
6+
part 'edit_category_event.dart';
7+
part 'edit_category_state.dart';
8+
9+
/// A BLoC to manage the state of editing a single category.
10+
class EditCategoryBloc extends Bloc<EditCategoryEvent, EditCategoryState> {
11+
/// {@macro edit_category_bloc}
12+
EditCategoryBloc({
13+
required HtDataRepository<Category> categoriesRepository,
14+
required String categoryId,
15+
}) : _categoriesRepository = categoriesRepository,
16+
_categoryId = categoryId,
17+
super(const EditCategoryState()) {
18+
on<EditCategoryLoaded>(_onLoaded);
19+
on<EditCategoryNameChanged>(_onNameChanged);
20+
on<EditCategoryDescriptionChanged>(_onDescriptionChanged);
21+
on<EditCategoryIconUrlChanged>(_onIconUrlChanged);
22+
on<EditCategorySubmitted>(_onSubmitted);
23+
}
24+
25+
final HtDataRepository<Category> _categoriesRepository;
26+
final String _categoryId;
27+
28+
Future<void> _onLoaded(
29+
EditCategoryLoaded event,
30+
Emitter<EditCategoryState> emit,
31+
) async {
32+
emit(state.copyWith(status: EditCategoryStatus.loading));
33+
try {
34+
final category = await _categoriesRepository.read(id: _categoryId);
35+
emit(
36+
state.copyWith(
37+
status: EditCategoryStatus.initial,
38+
initialCategory: category,
39+
name: category.name,
40+
description: category.description ?? '',
41+
iconUrl: category.iconUrl ?? '',
42+
),
43+
);
44+
} on HtHttpException catch (e) {
45+
emit(
46+
state.copyWith(
47+
status: EditCategoryStatus.failure,
48+
errorMessage: e.message,
49+
),
50+
);
51+
} catch (e) {
52+
emit(
53+
state.copyWith(
54+
status: EditCategoryStatus.failure,
55+
errorMessage: e.toString(),
56+
),
57+
);
58+
}
59+
}
60+
61+
void _onNameChanged(
62+
EditCategoryNameChanged event,
63+
Emitter<EditCategoryState> emit,
64+
) {
65+
emit(
66+
state.copyWith(
67+
name: event.name,
68+
// Reset status to allow for re-submission after a failure.
69+
status: EditCategoryStatus.initial,
70+
),
71+
);
72+
}
73+
74+
void _onDescriptionChanged(
75+
EditCategoryDescriptionChanged event,
76+
Emitter<EditCategoryState> emit,
77+
) {
78+
emit(
79+
state.copyWith(
80+
description: event.description,
81+
status: EditCategoryStatus.initial,
82+
),
83+
);
84+
}
85+
86+
void _onIconUrlChanged(
87+
EditCategoryIconUrlChanged event,
88+
Emitter<EditCategoryState> emit,
89+
) {
90+
emit(
91+
state.copyWith(
92+
iconUrl: event.iconUrl,
93+
status: EditCategoryStatus.initial,
94+
),
95+
);
96+
}
97+
98+
Future<void> _onSubmitted(
99+
EditCategorySubmitted event,
100+
Emitter<EditCategoryState> emit,
101+
) async {
102+
if (!state.isFormValid) return;
103+
104+
// Safely access the initial category to prevent null errors.
105+
final initialCategory = state.initialCategory;
106+
if (initialCategory == null) {
107+
emit(
108+
state.copyWith(
109+
status: EditCategoryStatus.failure,
110+
// TODO(l10n): Localize this message.
111+
errorMessage: 'Cannot update: Original category data not loaded.',
112+
),
113+
);
114+
return;
115+
}
116+
117+
emit(state.copyWith(status: EditCategoryStatus.submitting));
118+
try {
119+
// Use null for empty optional fields, which is cleaner for APIs.
120+
final updatedCategory = initialCategory.copyWith(
121+
name: state.name,
122+
description: state.description.isNotEmpty ? state.description : null,
123+
iconUrl: state.iconUrl.isNotEmpty ? state.iconUrl : null,
124+
);
125+
126+
await _categoriesRepository.update(
127+
id: _categoryId,
128+
item: updatedCategory,
129+
);
130+
emit(state.copyWith(status: EditCategoryStatus.success));
131+
} on HtHttpException catch (e) {
132+
emit(
133+
state.copyWith(
134+
status: EditCategoryStatus.failure,
135+
errorMessage: e.message,
136+
),
137+
);
138+
} catch (e) {
139+
emit(
140+
state.copyWith(
141+
status: EditCategoryStatus.failure,
142+
errorMessage: e.toString(),
143+
),
144+
);
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)