feat: Replace individual action icons with dropdown menu in users table
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Improved UX by consolidating user actions into a single dropdown menu: - Added MoreVert icon button to open actions menu - Menu includes: View Details, Edit User, Activate/Deactivate, Delete User - Delete action shown in error color for visual distinction - Cleaner table layout with single action button per row 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,10 @@ import {
|
||||
Grid,
|
||||
Switch,
|
||||
FormControlLabel,
|
||||
Menu,
|
||||
MenuItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
Search,
|
||||
@@ -36,6 +40,7 @@ import {
|
||||
PersonAdd,
|
||||
Block,
|
||||
CheckCircle,
|
||||
MoreVert,
|
||||
} from '@mui/icons-material';
|
||||
import AdminLayout from '@/components/AdminLayout';
|
||||
import apiClient from '@/lib/api-client';
|
||||
@@ -68,6 +73,8 @@ export default function UsersPage() {
|
||||
const [selectedUser, setSelectedUser] = useState<User | null>(null);
|
||||
const [viewDialogOpen, setViewDialogOpen] = useState(false);
|
||||
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const [menuUser, setMenuUser] = useState<User | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsers();
|
||||
@@ -92,14 +99,26 @@ export default function UsersPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenMenu = (event: React.MouseEvent<HTMLElement>, user: User) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
setMenuUser(user);
|
||||
};
|
||||
|
||||
const handleCloseMenu = () => {
|
||||
setAnchorEl(null);
|
||||
setMenuUser(null);
|
||||
};
|
||||
|
||||
const handleViewUser = (user: User) => {
|
||||
setSelectedUser(user);
|
||||
setViewDialogOpen(true);
|
||||
handleCloseMenu();
|
||||
};
|
||||
|
||||
const handleEditUser = (user: User) => {
|
||||
setSelectedUser(user);
|
||||
setEditDialogOpen(true);
|
||||
handleCloseMenu();
|
||||
};
|
||||
|
||||
const handleToggleUserStatus = async (user: User) => {
|
||||
@@ -108,6 +127,7 @@ export default function UsersPage() {
|
||||
emailVerified: !user.emailVerified,
|
||||
});
|
||||
fetchUsers();
|
||||
handleCloseMenu();
|
||||
} catch (error) {
|
||||
console.error('Failed to update user status:', error);
|
||||
}
|
||||
@@ -118,6 +138,7 @@ export default function UsersPage() {
|
||||
try {
|
||||
await apiClient.delete(`/admin/users/${userId}`);
|
||||
fetchUsers();
|
||||
handleCloseMenu();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete user:', error);
|
||||
}
|
||||
@@ -270,32 +291,10 @@ export default function UsersPage() {
|
||||
<TableCell align="right">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => handleViewUser(user)}
|
||||
title="View"
|
||||
onClick={(e) => handleOpenMenu(e, user)}
|
||||
title="Actions"
|
||||
>
|
||||
<Visibility />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => handleEditUser(user)}
|
||||
title="Edit"
|
||||
>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => handleToggleUserStatus(user)}
|
||||
title={user.emailVerified ? 'Deactivate' : 'Activate'}
|
||||
>
|
||||
{user.emailVerified ? <Block /> : <CheckCircle />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => handleDeleteUser(user.id)}
|
||||
title="Delete"
|
||||
color="error"
|
||||
>
|
||||
<Delete />
|
||||
<MoreVert />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -316,6 +315,43 @@ export default function UsersPage() {
|
||||
/>
|
||||
</TableContainer>
|
||||
|
||||
{/* Actions Menu */}
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleCloseMenu}
|
||||
>
|
||||
<MenuItem onClick={() => menuUser && handleViewUser(menuUser)}>
|
||||
<ListItemIcon>
|
||||
<Visibility fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>View Details</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => menuUser && handleEditUser(menuUser)}>
|
||||
<ListItemIcon>
|
||||
<Edit fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>Edit User</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => menuUser && handleToggleUserStatus(menuUser)}>
|
||||
<ListItemIcon>
|
||||
{menuUser?.emailVerified ? <Block fontSize="small" /> : <CheckCircle fontSize="small" />}
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
{menuUser?.emailVerified ? 'Deactivate' : 'Activate'}
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => menuUser && handleDeleteUser(menuUser.id)}
|
||||
sx={{ color: 'error.main' }}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Delete fontSize="small" color="error" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>Delete User</ListItemText>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
{/* View User Dialog */}
|
||||
<Dialog
|
||||
open={viewDialogOpen}
|
||||
|
||||
Reference in New Issue
Block a user