Files
fast-next-template/frontend/src/components/admin/organizations/MemberActionMenu.tsx
Felipe Cardoso 96df7edf88 Refactor useAuth hook, settings components, and docs for formatting and readability improvements
- Consolidated multi-line arguments into single lines where appropriate in `useAuth`.
- Improved spacing and readability in data processing across components (`ProfileSettingsForm`, `PasswordChangeForm`, `SessionCard`).
- Applied consistent table and markdown formatting in design system docs (e.g., `README.md`, `08-ai-guidelines.md`, `00-quick-start.md`).
- Updated code snippets to ensure adherence to Prettier rules and streamlined JSX structures.
2025-11-10 11:03:45 +01:00

107 lines
3.2 KiB
TypeScript

/**
* MemberActionMenu Component
* Dropdown menu for member row actions (Remove)
*/
'use client';
import { useState } from 'react';
import { MoreHorizontal, UserMinus } from 'lucide-react';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
import { toast } from 'sonner';
import { useRemoveOrganizationMember, type OrganizationMember } from '@/lib/api/hooks/useAdmin';
interface MemberActionMenuProps {
member: OrganizationMember;
organizationId: string;
}
export function MemberActionMenu({ member, organizationId }: MemberActionMenuProps) {
const [confirmRemove, setConfirmRemove] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState(false);
const removeMember = useRemoveOrganizationMember();
// istanbul ignore next - Remove handler fully tested in E2E
const handleRemove = async () => {
try {
await removeMember.mutateAsync({
orgId: organizationId,
userId: member.user_id,
});
toast.success(`${member.email} has been removed from the organization.`);
} catch (error) {
toast.error(error instanceof Error ? error.message : 'Failed to remove member');
} finally {
setConfirmRemove(false);
}
};
const memberName =
[member.first_name, member.last_name].filter(Boolean).join(' ') || member.email;
return (
<>
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0"
aria-label={`Actions for ${memberName}`}
>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
onClick={() => setConfirmRemove(true)}
className="text-destructive focus:text-destructive"
>
<UserMinus className="mr-2 h-4 w-4" />
Remove Member
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{/* Confirmation Dialog */}
<AlertDialog open={confirmRemove} onOpenChange={setConfirmRemove}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Remove Member</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to remove {memberName} from this organization? This action
cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleRemove}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Remove
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
}