/* eslint-disable react-hooks/rules-of-hooks */ import { useCallback, useEffect, useMemo, useState } from 'react'; import { Avatar, Button, ButtonGroup, Flex, Icon, IconButton, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Skeleton, Table, TableContainer, Tbody, Td, Text, Th, Thead, Tooltip, Tr, useColorModeValue, useToast } from '@chakra-ui/react'; import { Link } from '@chakra-ui/next-js'; import { useAuthContext } from '@/contexts/AuthContext'; import { Organization, OrganizationInvitation } from '@/types'; import { useRouter } from 'next/router'; import { BiRefresh } from 'react-icons/bi'; const moment = require('moment'); function TableEntry({ key, invitation, skeleton, action }: { key: number | string, invitation?: OrganizationInvitation, skeleton?: boolean, action: any }) { const toRelativeTime = useMemo(() => (date: any) => { return moment(new Date(date)).fromNow(); }, []); return <> {!skeleton ? invitation?.recipient?.displayName : "N/A"} @{invitation?.recipient?.username} {!skeleton ? toRelativeTime(invitation?.createdAt) : 'N/A'} {!skeleton ? invitation?.createdBy?.displayName : "N/A"} @{invitation?.createdBy?.username} } export default function OrganizationInvitationsModal({ isOpen, onClose, organization, onRefresh }: { isOpen: boolean; onClose: () => void; organization?: Organization | null; onRefresh: () => void; }) { const toast = useToast(); const { push } = useRouter(); const { user } = useAuthContext(); const [invitationsLoading, setInvitationsLoading] = useState(true); const [invitations, setInvitations] = useState([]); const fetchInvitations = useCallback(async () => { setInvitationsLoading(true); user.getIdToken().then(async (token: string) => { await fetch(`/api/v1/organizations/${organization?.id}/invitations`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }).then(async (res) => { const data = await res.json(); if (res.status === 200) { setInvitations(data || []); } else { toast({ title: "There was an error fetching the organization's invitations.", description: data.message, status: "error", duration: 9000, isClosable: true, }); } }).finally(() => { setInvitationsLoading(false); }); }); }, [user, toast, organization]); const actOnInvitation = useCallback(async (invitation: OrganizationInvitation, action: 'withdraw') => { setInvitationsLoading(true); await user.getIdToken().then(async (token: string) => { await fetch(`/api/v1/organizations/${organization?.id}/invitations/${invitation.id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }).then(async (res) => { const data = await res.json(); if (res.status === 200) { await fetchInvitations(); toast({ title: data.message, status: "success", duration: 5000, isClosable: true, }); } else { toast({ title: "There was an error taking action on an invitation.", description: data.message, status: "error", duration: 5000, isClosable: true, }); } }).finally(() => { setInvitationsLoading(false); }); }); }, [user, toast, fetchInvitations, organization?.id]); useEffect(() => { if (!user) return; if (!organization) return; if (!isOpen) return; fetchInvitations(); }, [user, fetchInvitations, organization, isOpen]); return ( <> Invitations } /> { invitationsLoading ? ( Array.from({ length: 6 }).map((_, i) => ( )) ) : (invitations.map((invitation: OrganizationInvitation) => ( ))) }
Recipient Invite Date Inviter Actions
{ !invitationsLoading && invitations.length === 0 && ( There are no outgoing invitations. ) }
); }