naim-firebase-auth-wrapper
Version:
React components and hooks for Firebase Authentication and Firestore with Mantine UI
65 lines • 4.43 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect, useCallback } from 'react';
import { Paper, Title, Table, Button, Text, Group, Badge, Loader, ActionIcon, Menu } from '@mantine/core';
import { IconDotsVertical, IconRefresh, IconSend, IconTrash } from '@tabler/icons-react';
import { getInvitationsByOrg, resendInvitation, cancelInvitation } from '../services/firestore';
export const InvitationList = ({ orgId, onResendSuccess, onCancelSuccess, onError, onInvitationResent }) => {
const [invitations, setInvitations] = useState([]);
const [loading, setLoading] = useState(true);
const loadInvitations = useCallback(async () => {
setLoading(true);
try {
const orgInvitations = await getInvitationsByOrg(orgId);
setInvitations(orgInvitations);
}
catch (error) {
console.error('Error loading invitations:', error);
onError?.(error);
}
finally {
setLoading(false);
}
}, [orgId, onError]);
useEffect(() => {
loadInvitations();
}, [loadInvitations]);
const handleResend = async (invitationId) => {
try {
const updatedInvitation = await resendInvitation(invitationId, {
onInvitationResent: (invitation) => {
// This will be called after the invitation is resent
onInvitationResent?.(invitation);
}
});
onResendSuccess?.(updatedInvitation.token, updatedInvitation.email, updatedInvitation.orgName, updatedInvitation.inviterName || '');
// Refresh the list
loadInvitations();
}
catch (error) {
console.error('Error resending invitation:', error);
onError?.(error);
}
};
const handleCancel = async (invitationId) => {
try {
await cancelInvitation(invitationId);
// Update local state
setInvitations(invitations.filter(inv => inv.id !== invitationId));
onCancelSuccess?.();
}
catch (error) {
console.error('Error canceling invitation:', error);
onError?.(error);
}
};
const formatDate = (date) => {
return new Date(date).toLocaleDateString();
};
if (loading) {
return _jsx(Loader, {});
}
return (_jsxs(Paper, { radius: "md", p: "xl", withBorder: true, children: [_jsxs(Group, { justify: "apart", mb: "md", children: [_jsx(Title, { order: 2, children: "Pending Invitations" }), _jsx(Button, { leftSection: _jsx(IconRefresh, { size: 16 }), variant: "subtle", onClick: loadInvitations, children: "Refresh" })] }), invitations.length === 0 ? (_jsx(Text, { color: "dimmed", children: "No pending invitations found." })) : (_jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Email" }), _jsx("th", { children: "Role" }), _jsx("th", { children: "Invited By" }), _jsx("th", { children: "Sent Date" }), _jsx("th", { children: "Expires" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Actions" })] }) }), _jsx("tbody", { children: invitations.map((invitation) => (_jsxs("tr", { children: [_jsx("td", { children: invitation.email }), _jsx("td", { style: { textTransform: 'capitalize' }, children: invitation.role }), _jsx("td", { children: invitation.inviterName }), _jsx("td", { children: formatDate(invitation.createdAt) }), _jsx("td", { children: formatDate(invitation.expiresAt) }), _jsx("td", { children: _jsx(Badge, { color: invitation.status === 'pending' ? 'blue' :
invitation.status === 'accepted' ? 'green' : 'red', children: invitation.status }) }), _jsx("td", { children: invitation.status === 'pending' && (_jsxs(Menu, { position: "bottom-end", children: [_jsx(Menu.Target, { children: _jsx(ActionIcon, { children: _jsx(IconDotsVertical, { size: 16 }) }) }), _jsxs(Menu.Dropdown, { children: [_jsx(Menu.Item, { leftSection: _jsx(IconSend, { size: 16 }), onClick: () => handleResend(invitation.id), children: "Resend Invitation" }), _jsx(Menu.Item, { leftSection: _jsx(IconTrash, { size: 16 }), onClick: () => handleCancel(invitation.id), color: "red", children: "Cancel Invitation" })] })] })) })] }, invitation.id))) })] }))] }));
};
//# sourceMappingURL=InvitationList.js.map