import React, { useState, useCallback, useEffect } from 'react'; import { Button, Center, Flex, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useDisclosure, useToast, Tabs, TabList, Tab, TabPanels, TabPanel, InputGroup, Input, InputRightElement, Text, Link, } from '@chakra-ui/react'; import { useClient } from 'urql'; import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa'; import { useDropzone } from 'react-dropzone'; import { validateEmail, validateURI } from '../utils'; import { InviteMembers } from '../graphql/mutation'; import { ArrayInputOperations } from '../constants'; import parseCSV from '../utils/parseCSV'; interface stateDataTypes { value: string; isInvalid: boolean; } interface requestParamTypes { emails: string[]; redirect_uri?: string; } const initData: stateDataTypes = { value: '', isInvalid: false, }; const InviteMembersModal = ({ updateUserList, disabled = true, }: { updateUserList: Function; disabled: boolean; }) => { const client = useClient(); const toast = useToast(); const { isOpen, onOpen, onClose } = useDisclosure(); const [tabIndex, setTabIndex] = useState(0); const [redirectURI, setRedirectURI] = useState({ ...initData, }); const [emails, setEmails] = useState([{ ...initData }]); const [disableSendButton, setDisableSendButton] = useState(false); const [loading, setLoading] = React.useState(false); useEffect(() => { if (redirectURI.isInvalid) { setDisableSendButton(true); } else if (emails.some((emailData) => emailData.isInvalid)) { setDisableSendButton(true); } else { setDisableSendButton(false); } }, [redirectURI, emails]); useEffect(() => { return () => { setRedirectURI({ ...initData }); setEmails([{ ...initData }]); }; }, []); const sendInviteHandler = async () => { setLoading(true); try { const emailList = emails .filter((emailData) => !emailData.isInvalid) .map((emailData) => emailData.value); const params: requestParamTypes = { emails: emailList, }; if (redirectURI.value !== '' && !redirectURI.isInvalid) { params.redirect_uri = redirectURI.value; } if (emailList.length > 0) { const res = await client .mutation(InviteMembers, { params, }) .toPromise(); if (res.error) { throw new Error('Internal server error'); return; } toast({ title: 'Invites sent successfully!', isClosable: true, status: 'success', position: 'bottom-right', }); setLoading(false); updateUserList(); } else { throw new Error('Please add emails'); } } catch (error: any) { toast({ title: error?.message || 'Error occurred, try again!', isClosable: true, status: 'error', position: 'bottom-right', }); setLoading(false); } closeModalHandler(); }; const updateEmailListHandler = (operation: string, index: number = 0) => { switch (operation) { case ArrayInputOperations.APPEND: setEmails([...emails, { ...initData }]); break; case ArrayInputOperations.REMOVE: const updatedEmailList = [...emails]; updatedEmailList.splice(index, 1); setEmails(updatedEmailList); break; default: break; } }; const inputChangeHandler = (value: string, index: number) => { const updatedEmailList = [...emails]; updatedEmailList[index].value = value; updatedEmailList[index].isInvalid = !validateEmail(value); setEmails(updatedEmailList); }; const changeTabsHandler = (index: number) => { setTabIndex(index); }; const onDrop = useCallback(async (acceptedFiles) => { const result = await parseCSV(acceptedFiles[0], ','); setEmails(result); changeTabsHandler(0); }, []); const setRedirectURIHandler = (value: string) => { const updatedRedirectURI: stateDataTypes = { value: '', isInvalid: false, }; updatedRedirectURI.value = value; updatedRedirectURI.isInvalid = !validateURI(value); setRedirectURI(updatedRedirectURI); }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: 'text/csv', }); const closeModalHandler = () => { setRedirectURI({ value: '', isInvalid: false, }); setEmails([ { value: '', isInvalid: false, }, ]); onClose(); }; return ( <> Invite Members Enter emails Upload CSV Redirect URI setRedirectURIHandler(e.currentTarget.value) } /> Emails {emails.map((emailData, index) => ( inputChangeHandler(e.currentTarget.value, index) } /> ))} {isDragActive ? ( Drop the files here... ) : (
Drag 'n' drop the csv file here, or click to select. Download{' '} e.stopPropagation()} > {' '} sample.csv {' '} and modify it.{' '}
)}
); }; export default InviteMembersModal;