11import 'package:core/core.dart' ;
22import 'package:flutter/material.dart' ;
33import '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;
75import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/app_localizations.dart' ;
86import '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}
1917class 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