import React, { useEffect, useRef, useState } from 'react'; import { Button, Center, Flex, Input, InputGroup, MenuItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Select, Text, useDisclosure, useToast, Alert, AlertIcon, Collapse, Box, TableContainer, Table, Thead, Tr, Th, Tbody, Td, Code, Radio, RadioGroup, Stack, Textarea, } from '@chakra-ui/react'; import { FaPlus, FaAngleDown, FaAngleUp } from 'react-icons/fa'; import { useClient } from 'urql'; import EmailEditor from 'react-email-editor'; import { UpdateModalViews, EmailTemplateInputDataFields, emailTemplateEventNames, emailTemplateVariables, EmailTemplateEditors, } from '../constants'; import { capitalizeFirstLetter } from '../utils'; import { AddEmailTemplate, EditEmailTemplate } from '../graphql/mutation'; interface selectedEmailTemplateDataTypes { [EmailTemplateInputDataFields.ID]: string; [EmailTemplateInputDataFields.EVENT_NAME]: string; [EmailTemplateInputDataFields.SUBJECT]: string; [EmailTemplateInputDataFields.CREATED_AT]: number; [EmailTemplateInputDataFields.TEMPLATE]: string; [EmailTemplateInputDataFields.DESIGN]: string; } interface UpdateEmailTemplateInputPropTypes { view: UpdateModalViews; selectedTemplate?: selectedEmailTemplateDataTypes; fetchEmailTemplatesData: Function; } interface templateVariableDataTypes { text: string; value: string; description: string; } interface emailTemplateDataType { [EmailTemplateInputDataFields.EVENT_NAME]: string; [EmailTemplateInputDataFields.SUBJECT]: string; [EmailTemplateInputDataFields.TEMPLATE]: string; [EmailTemplateInputDataFields.DESIGN]: string; } interface validatorDataType { [EmailTemplateInputDataFields.SUBJECT]: boolean; } const initTemplateData: emailTemplateDataType = { [EmailTemplateInputDataFields.EVENT_NAME]: emailTemplateEventNames.Signup, [EmailTemplateInputDataFields.SUBJECT]: '', [EmailTemplateInputDataFields.TEMPLATE]: '', [EmailTemplateInputDataFields.DESIGN]: '', }; const initTemplateValidatorData: validatorDataType = { [EmailTemplateInputDataFields.SUBJECT]: true, }; const UpdateEmailTemplate = ({ view, selectedTemplate, fetchEmailTemplatesData, }: UpdateEmailTemplateInputPropTypes) => { const client = useClient(); const toast = useToast(); const emailEditorRef = useRef(null); const { isOpen, onOpen, onClose } = useDisclosure(); const [loading, setLoading] = useState(false); const [editor, setEditor] = useState( EmailTemplateEditors.PLAIN_HTML_EDITOR, ); const [templateVariables, setTemplateVariables] = useState< templateVariableDataTypes[] >([]); const [templateData, setTemplateData] = useState({ ...initTemplateData, }); const [validator, setValidator] = useState({ ...initTemplateValidatorData, }); const [isDynamicVariableInfoOpen, setIsDynamicVariableInfoOpen] = useState(false); const onReady = () => { if (selectedTemplate) { const { design } = selectedTemplate; try { if (design) { const designData = JSON.parse(design); // @ts-ignore emailEditorRef.current.editor.loadDesign(designData); } } catch (error) { console.error(error); onClose(); } } }; const inputChangehandler = (inputType: string, value: any) => { if (inputType !== EmailTemplateInputDataFields.EVENT_NAME) { setValidator({ ...validator, [inputType]: value?.trim().length, }); } setTemplateData({ ...templateData, [inputType]: value }); }; const validateData = () => { return ( !loading && templateData[EmailTemplateInputDataFields.EVENT_NAME].length > 0 && templateData[EmailTemplateInputDataFields.SUBJECT].length > 0 && validator[EmailTemplateInputDataFields.SUBJECT] ); }; const updateTemplate = async (params: emailTemplateDataType) => { let res: any = {}; if ( view === UpdateModalViews.Edit && selectedTemplate?.[EmailTemplateInputDataFields.ID] ) { res = await client .mutation(EditEmailTemplate, { params: { ...params, id: selectedTemplate[EmailTemplateInputDataFields.ID], }, }) .toPromise(); } else { res = await client.mutation(AddEmailTemplate, { params }).toPromise(); } setLoading(false); if (res.error) { toast({ title: capitalizeFirstLetter(res.error.message), isClosable: true, status: 'error', position: 'bottom-right', }); } else if ( res.data?._add_email_template || res.data?._update_email_template ) { toast({ title: capitalizeFirstLetter( res.data?._add_email_template?.message || res.data?._update_email_template?.message, ), isClosable: true, status: 'success', position: 'bottom-right', }); setTemplateData({ ...initTemplateData, }); setValidator({ ...initTemplateValidatorData }); fetchEmailTemplatesData(); } }; const saveData = async () => { if (!validateData()) return; setLoading(true); let params: emailTemplateDataType = { [EmailTemplateInputDataFields.EVENT_NAME]: templateData[EmailTemplateInputDataFields.EVENT_NAME], [EmailTemplateInputDataFields.SUBJECT]: templateData[EmailTemplateInputDataFields.SUBJECT], [EmailTemplateInputDataFields.TEMPLATE]: templateData[EmailTemplateInputDataFields.TEMPLATE], [EmailTemplateInputDataFields.DESIGN]: '', }; if (editor === EmailTemplateEditors.UNLAYER_EDITOR) { // @ts-ignore await emailEditorRef.current.editor.exportHtml(async (data) => { const { design, html } = data; if (!html || !design) { setLoading(false); return; } params = { ...params, [EmailTemplateInputDataFields.TEMPLATE]: html.trim(), [EmailTemplateInputDataFields.DESIGN]: JSON.stringify(design), }; await updateTemplate(params); }); } else { await updateTemplate(params); } view === UpdateModalViews.ADD && onClose(); }; const resetData = () => { if (selectedTemplate) { setTemplateData(selectedTemplate); } else { setTemplateData({ ...initTemplateData }); } }; // set template data if edit modal is open useEffect(() => { if ( isOpen && view === UpdateModalViews.Edit && selectedTemplate && Object.keys(selectedTemplate || {}).length ) { const { id, created_at, ...rest } = selectedTemplate; setTemplateData(rest); } }, [isOpen]); // set template variables useEffect(() => { const updatedTemplateVariables = Object.entries( emailTemplateVariables, ).reduce((acc, [key, val]): any => { if ( (templateData[EmailTemplateInputDataFields.EVENT_NAME] !== emailTemplateEventNames['Verify Otp'] && val === emailTemplateVariables.otp) || (templateData[EmailTemplateInputDataFields.EVENT_NAME] === emailTemplateEventNames['Verify Otp'] && val === emailTemplateVariables.verification_url) ) { return acc; } return [ ...acc, { text: key, value: val.value, description: val.description, }, ]; }, []); setTemplateVariables(updatedTemplateVariables); }, [templateData[EmailTemplateInputDataFields.EVENT_NAME]]); // change editor useEffect(() => { if (isOpen && selectedTemplate) { const { design } = selectedTemplate; if (design) { setEditor(EmailTemplateEditors.UNLAYER_EDITOR); } else { setEditor(EmailTemplateEditors.PLAIN_HTML_EDITOR); } } }, [isOpen, selectedTemplate]); // reset fields when editor is changed useEffect(() => { if (selectedTemplate?.design) { if (editor === EmailTemplateEditors.UNLAYER_EDITOR) { setTemplateData({ ...templateData, [EmailTemplateInputDataFields.TEMPLATE]: selectedTemplate.template, [EmailTemplateInputDataFields.DESIGN]: selectedTemplate.design, }); } else { setTemplateData({ ...templateData, [EmailTemplateInputDataFields.TEMPLATE]: '', [EmailTemplateInputDataFields.DESIGN]: '', }); } } else if (selectedTemplate?.template) { if (editor === EmailTemplateEditors.UNLAYER_EDITOR) { setTemplateData({ ...templateData, [EmailTemplateInputDataFields.TEMPLATE]: '', [EmailTemplateInputDataFields.DESIGN]: '', }); } else { setTemplateData({ ...templateData, [EmailTemplateInputDataFields.TEMPLATE]: selectedTemplate?.template, [EmailTemplateInputDataFields.DESIGN]: '', }); } } }, [editor]); return ( <> {view === UpdateModalViews.ADD ? ( ) : ( Edit )} { resetData(); onClose(); }} size="6xl" > {view === UpdateModalViews.ADD ? 'Add New Email Template' : 'Edit Email Template'} setIsDynamicVariableInfoOpen(!isDynamicVariableInfoOpen) } borderRadius="5" marginBottom={5} cursor="pointer" fontSize="sm" > Note: You can add set of dynamic variables to subject and email body. Click here to see the set of dynamic variables. {isDynamicVariableInfoOpen ? : } {templateVariables.map((i) => ( ))}
Variable Description
{`{{.${i.text}}}`} {i.description}
Event Name Subject inputChangehandler( EmailTemplateInputDataFields.SUBJECT, e.currentTarget.value, ) } /> Template Body setEditor(value)} value={editor} > Plain HTML Unlayer Editor {editor === EmailTemplateEditors.UNLAYER_EDITOR ? ( ) : (