Skip to content

Commit

Permalink
refactor: real api - authorities
Browse files Browse the repository at this point in the history
  • Loading branch information
cevheri committed Dec 30, 2024
1 parent f5944a7 commit 2752382
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';

/// Dropdown widget for selecting user authorities/roles.
/// Displays available authority options from AuthorityBloc.
/// Updates when authority state changes.
class AuthorityDropdown extends StatelessWidget {
/// Updates when authorities state changes.
class AuthoritiesDropdown extends StatelessWidget {
final bool enabled;
final String? initialValue;

const AuthorityDropdown({super.key, this.enabled = true});
const AuthoritiesDropdown({super.key, this.enabled = true, this.initialValue});

@override
Widget build(BuildContext context) {
Expand All @@ -23,10 +24,10 @@ class AuthorityDropdown extends StatelessWidget {
final authorities = ["", ...state.authorities];
return FormBuilderDropdown(
enabled: enabled,
name: 'authority',
name: 'authorities',
decoration: InputDecoration(hintText: S.of(context).authorities),
items: authorities.map((e) => DropdownMenuItem(value: e, child: Text(e ?? ""))).toList(),
initialValue: authorities.first,
initialValue: initialValue ?? authorities.first,
);
}
return const SizedBox.shrink();
Expand Down
12 changes: 6 additions & 6 deletions lib/presentation/screen/user/bloc/user_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,21 @@ class UserBloc extends Bloc<UserEvent, UserState> {

/// Search a user by name or authority.
FutureOr<void> _onSearch(UserSearchEvent event, Emitter<UserState> emit) async {
_log.debug("BEGIN: onSearch UserSearch event. name:{} authority: {}", [event.name, event.authority]);
_log.debug("BEGIN: onSearch UserSearch event. name:{} authority: {}", [event.name, event.authorities]);
emit(state.copyWith(status: UserStatus.loading));
try {
if ((event.name == null || event.name == "") && (event.authority == null || event.authority == "")) {
if ((event.name == null || event.name == "") && (event.authorities == null || event.authorities == "")) {
final entities = await _repository.list();
emit(state.copyWith(status: UserStatus.searchSuccess, userList: entities));
_log.debug("END:onSearch UserSearch event success - list. content count: {}", [entities.length]);
return;
} else if (event.name != null && event.name!.isNotEmpty && event.authority != null && event.authority!.isNotEmpty) {
final entities = await _repository.listByNameAndRole(event.page, event.size, event.name!, event.authority!);
} else if (event.name != null && event.name!.isNotEmpty && event.authorities != null && event.authorities!.isNotEmpty) {
final entities = await _repository.listByNameAndRole(event.page, event.size, event.name!, event.authorities!);
emit(state.copyWith(status: UserStatus.searchSuccess, userList: entities));
_log.debug("END:onSearch UserSearch event with name success - name and authority content count: {}", [entities.length]);
return;
} else if (event.authority != null && event.authority!.isNotEmpty) {
final entities = await _repository.listByAuthority(event.page, event.size, event.authority!);
} else if (event.authorities != null && event.authorities!.isNotEmpty) {
final entities = await _repository.listByAuthority(event.page, event.size, event.authorities!);
emit(state.copyWith(status: UserStatus.searchSuccess, userList: entities));
_log.debug("END:onSearch UserSearch event success authority - content count: {}", [entities.length]);
return;
Expand Down
4 changes: 2 additions & 2 deletions lib/presentation/screen/user/bloc/user_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ class UserEvent extends Equatable {
class UserSearchEvent extends UserEvent {
final int page;
final int size;
final String? authority;
final String? authorities;
final String? name;

const UserSearchEvent({
this.page = 0,
this.size = 10,
this.authority,
this.authorities,
this.name,
});
}
Expand Down
17 changes: 5 additions & 12 deletions lib/presentation/screen/user/editor/user_editor_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bloc_advance/data/models/user.dart';
import 'package:flutter_bloc_advance/generated/l10n.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authority_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authorities_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/editor_form_mode.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/responsive_form_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/submit_button_widget.dart';
Expand Down Expand Up @@ -46,10 +46,7 @@ class UserEditorWidget extends StatelessWidget {
final _formKey = GlobalKey<FormBuilderState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();

UserEditorWidget({
super.key,
required this.mode,
});
UserEditorWidget({super.key, required this.mode});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -149,7 +146,7 @@ class UserEditorWidget extends StatelessWidget {
'lastName': state.data?.lastName ?? '',
'email': state.data?.email ?? '',
'activated': state.data?.activated ?? true,
'authorities': state.data?.authorities?.first ?? state.data?.authorities?.firstOrNull,
'authorities': state.data?.authorities?.firstOrNull ?? '',
};
debugPrint("checkpoint initial value: $initialValue");
return ResponsiveFormBuilder(
Expand Down Expand Up @@ -196,7 +193,7 @@ class UserEditorWidget extends StatelessWidget {
email: formData['email'],
activated: formData['activated'],
langKey: 'en',
authorities: [formData['authority'] ?? ''],
authorities: [formData['authorities'] ?? ''],
);

context.read<UserBloc>().add(UserSubmitEvent(user));
Expand All @@ -213,11 +210,7 @@ class UserEditorWidget extends StatelessWidget {
UserFormFields.lastNameField(context, state.data?.lastName, enabled: mode != EditorFormMode.view),
UserFormFields.emailField(context, state.data?.email, enabled: mode != EditorFormMode.view),
UserFormFields.activatedField(context, state.data?.activated, enabled: mode != EditorFormMode.view),
//TODO when mode == EditorFormMode.view, select the user authorities
// if (state.data?.authorities?.isNotEmpty ?? false) ...[
// const SizedBox(height: 16),
// ],
AuthorityDropdown(enabled: mode != EditorFormMode.view),
AuthoritiesDropdown(enabled: mode != EditorFormMode.view, initialValue: state.data?.authorities?.firstOrNull),
];
}

Expand Down
12 changes: 6 additions & 6 deletions lib/presentation/screen/user/list/list_user_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bloc_advance/configuration/padding_spacing.dart';
import 'package:flutter_bloc_advance/generated/l10n.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authority_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authorities_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/user/bloc/user.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:go_router/go_router.dart';

/// Main screen widget for displaying user list functionality.
/// Handles authority loading and user state changes.
/// Handles authorities loading and user state changes.
/// Contains the main layout structure and search functionality.
class ListUserScreen extends StatelessWidget {
ListUserScreen({super.key});
Expand Down Expand Up @@ -122,7 +122,7 @@ class UserListContent extends StatelessWidget {
}

/// Search section widget that contains filtering options.
/// Includes authority dropdown, pagination controls, and name search.
/// Includes authorities dropdown, pagination controls, and name search.
/// Manages form state for search parameters.
class UserSearchSection extends StatelessWidget {
final GlobalKey<FormBuilderState> formKey;
Expand All @@ -144,7 +144,7 @@ class UserSearchSection extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
children: [
SizedBox(width: 75, child: Text(S.of(context).filter)),
const Flexible(flex: 2, child: AuthorityDropdown()),
const Flexible(flex: 2, child: AuthoritiesDropdown()),
const SizedBox(width: 200, child: PaginationControls()),
const Flexible(child: SearchNameField()),
SearchActionButtons(formKey: formKey),
Expand Down Expand Up @@ -264,7 +264,7 @@ class SearchActionButtons extends StatelessWidget {
UserSearchEvent(
page: int.parse(formKey.currentState!.fields['rangeStart']?.value),
size: int.parse(formKey.currentState!.fields['rangeEnd']?.value),
authority: formKey.currentState!.fields['authority']?.value,
authorities: formKey.currentState!.fields['authorities']?.value,
name: formKey.currentState!.fields['name']?.value,
),
);
Expand Down Expand Up @@ -561,7 +561,7 @@ class UserActionButtons extends StatelessWidget {
UserSearchEvent(
page: int.parse(formKey.currentState!.fields['rangeStart']?.value),
size: int.parse(formKey.currentState!.fields['rangeEnd']?.value),
authority: formKey.currentState!.fields['authority']?.value,
authorities: formKey.currentState!.fields['authorities']?.value,
name: formKey.currentState!.fields['name']?.value,
),
);
Expand Down
6 changes: 3 additions & 3 deletions test/presentation/blocs/user_bloc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void main() {
when(repository.listByAuthority(0, 10, "ROLE_USER")).thenAnswer((_) async => users);
},
build: () => bloc,
act: (bloc) => bloc.add(const UserSearchEvent(authority: "ROLE_USER")),
act: (bloc) => bloc.add(const UserSearchEvent(authorities: "ROLE_USER")),
expect: () => [
const UserState(status: UserStatus.loading),
const UserState(status: UserStatus.searchSuccess, userList: users),
Expand All @@ -162,7 +162,7 @@ void main() {
build: () => bloc,
act: (bloc) => bloc.add(const UserSearchEvent(
name: "Test",
authority: "ROLE_USER",
authorities: "ROLE_USER",
)),
expect: () => [
const UserState(status: UserStatus.loading),
Expand All @@ -176,7 +176,7 @@ void main() {
when(repository.listByAuthority(0, 10, "ROLE_USER")).thenThrow(Exception('Search failed'));
},
build: () => bloc,
act: (bloc) => bloc.add(const UserSearchEvent(authority: "ROLE_USER")),
act: (bloc) => bloc.add(const UserSearchEvent(authorities: "ROLE_USER")),
expect: () => [
const UserState(status: UserStatus.loading),
const UserState(status: UserStatus.failure, err: "Exception: Search failed"),
Expand Down
4 changes: 2 additions & 2 deletions test/presentation/screen/user/user_editor_screen_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:flutter_bloc_advance/data/repository/authority_repository.dart';
import 'package:flutter_bloc_advance/data/repository/user_repository.dart';
import 'package:flutter_bloc_advance/generated/l10n.dart';
import 'package:flutter_bloc_advance/presentation/common_blocs/authority/authority.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authority_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/authorities_lov_widget.dart';
import 'package:flutter_bloc_advance/presentation/screen/components/editor_form_mode.dart';
import 'package:flutter_bloc_advance/presentation/screen/user/bloc/user.dart';
import 'package:flutter_bloc_advance/routes/go_router_routes/routes/user_routes.dart';
Expand Down Expand Up @@ -117,7 +117,7 @@ void main() {
expect(find.byKey(const Key('userEditorLastNameFieldKey')), findsOneWidget);
expect(find.byKey(const Key('userEditorEmailFieldKey')), findsOneWidget);
expect(find.byKey(const Key('userEditorActivatedFieldKey')), findsOneWidget);
expect(find.byType(AuthorityDropdown), findsOneWidget);
expect(find.byType(AuthoritiesDropdown), findsOneWidget);

// Verify bloc interactions
verify(mockUserBloc.add(any)).called(1);
Expand Down

0 comments on commit 2752382

Please sign in to comment.