Skip to content

Commit ae959c8

Browse files
committed
refactor(user_management): Align user action buttons with content actions
- Refactored `UserActionButtons` to display a primary action icon directly in the table row. - Secondary actions (like "Copy User ID") are now in a `PopupMenuButton` (ellipsis icon). - This change mimics the UI pattern of `ContentActionButtons`, creating a consistent user experience across the dashboard. - The primary action is now an `IconButton` for "Promote" or "Demote", depending on the user's role.
1 parent 3621a6c commit ae959c8

File tree

1 file changed

+66
-68
lines changed

1 file changed

+66
-68
lines changed
Lines changed: 66 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
import 'package:core/core.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter/services.dart';
4-
import 'package:flutter_bloc/flutter_bloc.dart';
5-
import 'package:flutter_news_app_web_dashboard_full_source_code/content_management/widgets/content_action_buttons.dart'
6-
show ContentActionButtons;
4+
import 'package:flutter_bloc/flutter_bloc.dart' show ReadContext;
75
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/app_localizations.dart';
86
import 'package:flutter_news_app_web_dashboard_full_source_code/user_management/bloc/user_management_bloc.dart';
9-
import 'package:ui_kit/ui_kit.dart';
107

118
/// {@template user_action_buttons}
129
/// A widget that displays contextual action buttons for a user in the user
1310
/// management table.
1411
///
1512
/// Actions are presented in a [PopupMenuButton] and are conditionally
1613
/// displayed based on the user's role and permissions. This follows a similar
17-
/// pattern to [ContentActionButtons] but is tailored for user management.
14+
/// pattern to the content management action buttons but is tailored for user
15+
/// management.
1816
/// {@endtemplate}
1917
class UserActionButtons extends StatelessWidget {
2018
/// {@macro user_action_buttons}
@@ -32,95 +30,95 @@ class UserActionButtons extends StatelessWidget {
3230

3331
@override
3432
Widget build(BuildContext context) {
33+
// visibleActions holds the primary action icons that are always visible.
34+
final visibleActions = <Widget>[];
35+
// overflowMenuItems holds actions that are in the popup menu.
3536
final overflowMenuItems = <PopupMenuEntry<String>>[];
3637

3738
// Rule: Do not show any actions for admin users.
3839
if (user.dashboardRole == DashboardUserRole.admin) {
3940
return const SizedBox.shrink();
4041
}
41-
42-
// Add contextual actions based on the user's current dashboard role.
42+
// Primary action: Copy User ID. This is always available for non-admins.
43+
visibleActions.add(
44+
IconButton(
45+
visualDensity: VisualDensity.compact,
46+
iconSize: 20,
47+
icon: const Icon(Icons.copy),
48+
tooltip: l10n.copyId,
49+
onPressed: () => _onCopyId(context),
50+
),
51+
);
52+
// Add contextual actions to the overflow menu based on the user's role.
4353
switch (user.dashboardRole) {
4454
case DashboardUserRole.none:
4555
overflowMenuItems.add(
4656
PopupMenuItem<String>(
4757
value: 'promote',
48-
child: Row(
49-
children: [
50-
const Icon(Icons.arrow_upward),
51-
const SizedBox(width: AppSpacing.sm),
52-
Text(l10n.promoteToPublisher),
53-
],
54-
),
58+
child: Text(l10n.promoteToPublisher),
5559
),
5660
);
5761
case DashboardUserRole.publisher:
5862
overflowMenuItems.add(
5963
PopupMenuItem<String>(
6064
value: 'demote',
61-
child: Row(
62-
children: [
63-
const Icon(Icons.arrow_downward),
64-
const SizedBox(width: AppSpacing.sm),
65-
Text(l10n.demoteToUser),
66-
],
67-
),
65+
child: Text(l10n.demoteToUser),
6866
),
6967
);
7068
case DashboardUserRole.admin:
7169
// No actions for admins, handled by the initial check.
7270
break;
7371
}
74-
75-
// Add the "Copy User ID" action for all non-admin users.
76-
overflowMenuItems.add(
77-
PopupMenuItem<String>(
78-
value: 'copy_id',
79-
child: Row(
80-
children: [
81-
const Icon(Icons.copy),
82-
const SizedBox(width: AppSpacing.sm),
83-
Text(l10n.copyId),
84-
],
72+
// Add the overflow menu button if there are items in it.
73+
if (overflowMenuItems.isNotEmpty) {
74+
visibleActions.add(
75+
SizedBox(
76+
width: 32,
77+
child: PopupMenuButton<String>(
78+
iconSize: 20,
79+
icon: const Icon(Icons.more_vert),
80+
tooltip: l10n.moreActions,
81+
onSelected: (value) {
82+
switch (value) {
83+
case 'promote':
84+
_onPromote(context);
85+
case 'demote':
86+
_onDemote(context);
87+
}
88+
},
89+
itemBuilder: (context) => overflowMenuItems,
90+
),
8591
),
86-
),
87-
);
88-
92+
);
93+
}
8994
return Row(
9095
mainAxisSize: MainAxisSize.min,
91-
children: [
92-
PopupMenuButton<String>(
93-
iconSize: 20,
94-
icon: const Icon(Icons.more_vert),
95-
tooltip: l10n.moreActions,
96-
onSelected: (value) {
97-
switch (value) {
98-
case 'promote':
99-
context.read<UserManagementBloc>().add(
100-
UserDashboardRoleChanged(
101-
userId: user.id,
102-
dashboardRole: DashboardUserRole.publisher,
103-
),
104-
);
105-
case 'demote':
106-
context.read<UserManagementBloc>().add(
107-
UserDashboardRoleChanged(
108-
userId: user.id,
109-
dashboardRole: DashboardUserRole.none,
110-
),
111-
);
112-
case 'copy_id':
113-
Clipboard.setData(ClipboardData(text: user.id));
114-
ScaffoldMessenger.of(context)
115-
..hideCurrentSnackBar()
116-
..showSnackBar(
117-
SnackBar(content: Text(l10n.idCopiedToClipboard(user.id))),
118-
);
119-
}
120-
},
121-
itemBuilder: (context) => overflowMenuItems,
122-
),
123-
],
96+
children: visibleActions,
12497
);
12598
}
99+
100+
void _onPromote(BuildContext context) =>
101+
context.read<UserManagementBloc>().add(
102+
UserDashboardRoleChanged(
103+
userId: user.id,
104+
dashboardRole: DashboardUserRole.publisher,
105+
),
106+
);
107+
108+
void _onDemote(BuildContext context) =>
109+
context.read<UserManagementBloc>().add(
110+
UserDashboardRoleChanged(
111+
userId: user.id,
112+
dashboardRole: DashboardUserRole.none,
113+
),
114+
);
115+
116+
void _onCopyId(BuildContext context) {
117+
Clipboard.setData(ClipboardData(text: user.id));
118+
ScaffoldMessenger.of(context)
119+
..hideCurrentSnackBar()
120+
..showSnackBar(
121+
SnackBar(content: Text(l10n.idCopiedToClipboard(user.id))),
122+
);
123+
}
126124
}

0 commit comments

Comments
 (0)