Created
February 5, 2024 04:27
-
-
Save PRA1995SAG/910d92735e3a13ccc16e771ab87bfb5c to your computer and use it in GitHub Desktop.
Template modal component | messageTemplateSendHandler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable import/no-cycle */ | |
/* eslint-disable camelcase */ | |
/* eslint-disable react-native/no-raw-text */ | |
import { View, StyleSheet, Keyboard, Text } from "react-native"; | |
import React, { | |
Dispatch, | |
SetStateAction, | |
memo, | |
useEffect, | |
useRef, | |
useState, | |
} from "react"; | |
import Config from "react-native-config"; | |
import VectorImage from "react-native-vector-image"; | |
import CustomModal from "../../CustomModal.tsx"; | |
import { | |
COLORS, | |
IMAGE_PATH, | |
SCREEN_HEIGHT, | |
STRINGS, | |
} from "../../../constants/index.ts"; | |
import TemplateModalFooter from "./TemplateModalFooter.tsx"; | |
import TemplateModalBody from "./TemplateModalBody.tsx"; | |
import ModalHeader from "../../Modal/ModalHeader.tsx"; | |
import { authFetch, showToast } from "../../../utils/index.ts"; | |
import type { Templates } from "../../../types/templates.d.ts"; | |
import CustomButton from "../../CustomButton.tsx"; | |
import TemplateError from "../TemplateError/TemplateError.tsx"; | |
interface ActionsModalType { | |
isModalVisible: boolean; | |
setIsModalVisible: Dispatch<SetStateAction<boolean>>; | |
contactId: number; | |
contactNumber: string; | |
onTemplateModalHide?: () => void; | |
} | |
const TemplateModal = ({ | |
isModalVisible, | |
contactId, | |
setIsModalVisible, | |
onTemplateModalHide, | |
contactNumber, | |
}: ActionsModalType) => { | |
const [messageTemplateItems, setMessageTemplateItems] = useState< | |
{ label: string; value: number }[] | |
>([]); | |
const [messageTemplateData, setMessageTemplateData] = useState<Templates[]>( | |
[], | |
); | |
const [messageTemplateValue, setMessageTemplateValue] = useState< | |
number | null | |
>(null); | |
const [expandTemplate, setExpandTemplate] = useState(false); | |
const [sendTemplateLoading, setSendTemplateLoading] = useState(false); | |
const [headerVarItems, setHeaderVarItems] = useState<[]>([]); | |
const [headerDrValue, setHeaderDrValue] = useState<string | null>(null); | |
const [headerMediaCustomUrl, setHeaderMediaCustomUrl] = useState(""); | |
const [bodyVarsItems, setBodyVarsItems] = useState([]); | |
const [bodyDrValues, setBodyDrValues] = useState([""]); | |
const [bodyVarsCustomUrls, setBodyVarsCustomUrls] = useState<string[]>([""]); | |
const [buttonVarItems, setButtonVarItems] = useState<[]>([]); | |
const [buttonDrValues, setButtonDrValues] = useState([""]); | |
const [buttonCustomUrls, setButtonCustomUrls] = useState<string[]>([""]); | |
const [buttonVariableTypes, setButtonVariableTypes] = useState<string[]>([]); | |
const [errorMessage, setErrorMessage] = useState(""); | |
const [headerError, setHeaderError] = useState({ | |
isDropdownValid: true, | |
isCustomValValid: true, | |
}); | |
const [bodyErrors, setBodyErrors] = useState< | |
{ isDropdownValid: boolean; isCustomValValid: boolean }[] | |
>([]); | |
const [buttonErrors, setButtonErrors] = useState< | |
{ | |
isDropdownValid: boolean; | |
isCustomValValid: boolean; | |
}[] | |
>([]); | |
const haveFormErrorRef = useRef<boolean>(false); | |
const modalBodyScrollRef = useRef(null); | |
const closeTemplateModal = () => { | |
setIsModalVisible((prevState) => !prevState); | |
}; | |
const modalStyle = expandTemplate ? { flex: 1 } : undefined; | |
const hasHeaderVariables = headerVarItems.length > 0; | |
const hasButtonVariables = buttonVarItems.length > 0; | |
const bodyVarsItemsLength = bodyVarsItems.length; | |
const buttonVarsItemsLength = buttonVarItems.length; | |
const templatePreviewData = | |
messageTemplateData[ | |
messageTemplateItems.findIndex( | |
(temp) => temp.value === messageTemplateValue, | |
) | |
] || []; | |
const messageTemplateSendHandler = () => { | |
Keyboard.dismiss(); | |
if (!messageTemplateValue) { | |
showToast(STRINGS.SELECT_A_MESSAGE_TEMPLATE); | |
return; | |
} | |
if (hasHeaderVariables && !headerDrValue) { | |
setHeaderError(() => ({ | |
isCustomValValid: true, | |
isDropdownValid: false, | |
})); | |
return; | |
} | |
if ( | |
hasHeaderVariables && | |
headerDrValue === "custom" && | |
!headerMediaCustomUrl | |
) { | |
setHeaderError({ isCustomValValid: false, isDropdownValid: true }); | |
return; | |
} | |
const headerMapping = { merge_tag: headerDrValue }; | |
if (headerDrValue === "custom") { | |
headerMapping.custom_value = headerMediaCustomUrl; | |
} | |
const bodyMapping = []; | |
for (let i = 0; i < bodyVarsItemsLength; i += 1) { | |
const bodyDrValue = bodyDrValues[i]; | |
if (!bodyDrValue) { | |
setBodyErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[i] = { | |
isDropdownValid: false, | |
isCustomValValid: updatedState[i]?.isCustomValValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = true; | |
} | |
const mappingObj = { merge_tag: bodyDrValue }; | |
if (bodyDrValue === "custom") { | |
if (!bodyVarsCustomUrls[i]) { | |
setBodyErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[i] = { | |
isCustomValValid: false, | |
isDropdownValid: true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = true; | |
} | |
mappingObj.custom_value = bodyVarsCustomUrls[i]; | |
} | |
bodyMapping.push(mappingObj); | |
} | |
const buttonMapping = []; | |
for (let j = 0; j < buttonVarsItemsLength; j++) { | |
const buttonDrValue = buttonDrValues[j]; | |
if (!buttonDrValue) { | |
setButtonErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[j] = { | |
isDropdownValid: false, | |
isCustomValValid: updatedState[j]?.isCustomValValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = true; | |
} | |
const mappingObj = { merge_tag: buttonDrValue }; | |
if (buttonDrValue === "custom") { | |
if (!buttonCustomUrls[j]) { | |
setButtonErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[j] = { | |
isCustomValValid: false, | |
isDropdownValid: true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = true; | |
} | |
mappingObj.custom_value = buttonCustomUrls[j]; | |
} | |
buttonMapping.push(mappingObj); | |
} | |
if (haveFormErrorRef.current) { | |
return; | |
} | |
const variable_mapping = {}; | |
if (headerMapping.merge_tag) { | |
variable_mapping.header = [headerMapping]; | |
} | |
// console.log("button mapping: ", buttonMapping); | |
if (buttonMapping.length) { | |
for (let i = 0; i < buttonMapping?.length; i++) { | |
variable_mapping[buttonVariableTypes[i]] = [buttonMapping[i]]; | |
} | |
} | |
if (bodyMapping.length) { | |
variable_mapping.body = bodyMapping; | |
} | |
if ( | |
hasHeaderVariables && | |
templatePreviewData.variable_mapping.header?.type !== "text" | |
) { | |
variable_mapping.header = { | |
media: headerMapping, | |
}; | |
} | |
const apiBody = { | |
type: "template", | |
message: { | |
template_id: messageTemplateValue, | |
variable_mapping, | |
}, | |
}; | |
setSendTemplateLoading(true); | |
authFetch( | |
`${Config.WANOTIFIER_API_ENDPOINT}wanotifier/v1/conversations/${contactId}/message`, | |
{ | |
method: "POST", | |
body: JSON.stringify(apiBody), | |
}, | |
) | |
.then((res) => res.json()) | |
.then((result) => { | |
if (!result.error) { | |
showToast(`Message template sent successfully to ${contactNumber}`); | |
setIsModalVisible(false); | |
setErrorMessage(""); | |
} else { | |
setErrorMessage(result.message); | |
modalBodyScrollRef?.current?.scrollTo({ x: 0, y: 0, animated: true }); | |
} | |
}) | |
.catch(() => { | |
// console.log("template modal request error: ", e); | |
}) | |
.finally(() => { | |
setSendTemplateLoading(false); | |
}); | |
}; | |
useEffect(() => { | |
if (isModalVisible) { | |
authFetch(`${Config.WANOTIFIER_API_ENDPOINT}wanotifier/v1/templates`) | |
.then((res) => res.json()) | |
.then((result: Templates[]) => { | |
const templates = result.map((template) => ({ | |
label: template.name, | |
value: template.id, | |
})); | |
setMessageTemplateData(result); | |
setMessageTemplateItems(templates); | |
}); | |
} | |
return () => { | |
setHeaderMediaCustomUrl(""); | |
setBodyVarsCustomUrls([""]); | |
setButtonCustomUrls([""]); | |
setMessageTemplateValue(null); | |
setExpandTemplate(false); | |
setHeaderDrValue(null); | |
setHeaderVarItems([]); | |
setBodyVarsItems([]); | |
setButtonVarItems([]); | |
setBodyDrValues([""]); | |
setButtonDrValues([""]); | |
}; | |
}, [isModalVisible]); | |
useEffect(() => { | |
if (hasHeaderVariables && headerDrValue) { | |
setHeaderError((prevState) => ({ | |
isCustomValValid: prevState.isCustomValValid, | |
isDropdownValid: true, | |
})); | |
} | |
if ( | |
hasHeaderVariables && | |
headerDrValue === "custom" && | |
headerMediaCustomUrl | |
) { | |
setHeaderError((prevState) => ({ | |
isCustomValValid: true, | |
isDropdownValid: prevState.isDropdownValid, | |
})); | |
} | |
for (let i = 0; i < bodyVarsItemsLength; i += 1) { | |
const bodyDrValue = bodyDrValues[i]; | |
if (bodyDrValue) { | |
setBodyErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[i] = { | |
isDropdownValid: true, | |
isCustomValValid: updatedState[i]?.isCustomValValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = false; | |
} | |
if (bodyDrValue === "custom") { | |
if (bodyVarsCustomUrls[i]) { | |
setBodyErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[i] = { | |
isCustomValValid: true, | |
isDropdownValid: updatedState[i]?.isDropdownValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = false; | |
return; | |
} | |
} | |
} | |
for (let j = 0; j < buttonVarsItemsLength; j += 1) { | |
const buttonDrValue = buttonDrValues[j]; | |
if (buttonDrValue) { | |
setButtonErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[j] = { | |
isDropdownValid: true, | |
isCustomValValid: updatedState[j]?.isCustomValValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = false; | |
} | |
if (buttonDrValue === "custom") { | |
if (bodyVarsCustomUrls[j]) { | |
setBodyErrors((prevState) => { | |
const updatedState = [...prevState]; | |
updatedState[j] = { | |
isCustomValValid: true, | |
isDropdownValid: updatedState[j]?.isDropdownValid ?? true, | |
}; | |
return updatedState; | |
}); | |
haveFormErrorRef.current = false; | |
return; | |
} | |
} | |
} | |
}, [ | |
buttonCustomUrls, | |
buttonDrValues, | |
headerDrValue, | |
hasButtonVariables, | |
hasHeaderVariables, | |
headerMediaCustomUrl, | |
bodyDrValues, | |
bodyVarsCustomUrls, | |
bodyVarsItemsLength, | |
buttonVarsItemsLength, | |
]); | |
useEffect(() => { | |
setHeaderDrValue(null); | |
setHeaderVarItems([]); | |
setHeaderMediaCustomUrl(""); | |
setBodyVarsItems([]); | |
setBodyDrValues([""]); | |
setBodyVarsCustomUrls([""]); | |
setButtonVarItems([]); | |
setButtonCustomUrls([""]); | |
setButtonDrValues([""]); | |
setHeaderError({ | |
isDropdownValid: true, | |
isCustomValValid: true, | |
}); | |
setBodyErrors([]); | |
setButtonErrors([]); | |
setErrorMessage(""); | |
haveFormErrorRef.current = false; | |
}, [messageTemplateValue]); | |
return ( | |
<CustomModal | |
animationIn="fadeInDown" | |
animationOut="fadeOutUp" | |
propagateSwipe | |
handleBackdrop={() => closeTemplateModal()} | |
isVisible={isModalVisible} | |
modalStyle={modalStyle} | |
backdropOpacity={0.2} | |
onModalHide={onTemplateModalHide} | |
> | |
<View style={styles.modalContainer}> | |
<ModalHeader | |
headerComponent={ | |
<View style={styles.headerCompContainer}> | |
<Text style={styles.headerCompText}>Send Message Template</Text> | |
<CustomButton | |
onPress={closeTemplateModal} | |
buttonComp={<VectorImage source={IMAGE_PATH.closeGrayIcon} />} | |
/> | |
</View> | |
} | |
/> | |
<TemplateError errorMessage={errorMessage} /> | |
<TemplateModalBody | |
modalBodyScrollRef={modalBodyScrollRef} | |
headerError={headerError} | |
buttonErrors={buttonErrors} | |
bodyErrors={bodyErrors} | |
templateItems={messageTemplateItems} | |
templatePreviewData={templatePreviewData} | |
setExpandTemplate={setExpandTemplate} | |
headerVarItems={headerVarItems} | |
setHeaderVarItems={setHeaderVarItems} | |
headerDrValue={headerDrValue} | |
setHeaderDrValue={setHeaderDrValue} | |
headerMediaCustomUrl={headerMediaCustomUrl} | |
setHeaderMediaCustomUrl={setHeaderMediaCustomUrl} | |
bodyVarsItems={bodyVarsItems} | |
setBodyVarsItems={setBodyVarsItems} | |
bodyDrValues={bodyDrValues} | |
setBodyDrValues={setBodyDrValues} | |
bodyVarsCustomUrls={bodyVarsCustomUrls} | |
setBodyVarsCustomUrls={setBodyVarsCustomUrls} | |
buttonVarItems={buttonVarItems} | |
setButtonVarItems={setButtonVarItems} | |
buttonDrValues={buttonDrValues} | |
setButtonDrValues={setButtonDrValues} | |
buttonCustomUrls={buttonCustomUrls} | |
setButtonCustomUrls={setButtonCustomUrls} | |
messageTemplateValue={messageTemplateValue} | |
setMessageTemplateValue={setMessageTemplateValue} | |
setButtonVariableTypes={setButtonVariableTypes} | |
/> | |
<TemplateModalFooter | |
rightButtonDisabled={!messageTemplateValue} | |
isSendingTemplate={sendTemplateLoading} | |
leftButtonDisabled={sendTemplateLoading} | |
handleClose={() => closeTemplateModal()} | |
handleSend={messageTemplateSendHandler} | |
/> | |
</View> | |
</CustomModal> | |
); | |
}; | |
TemplateModal.defaultProps = { onTemplateModalHide: () => {} }; | |
TemplateModal.Header = ModalHeader; | |
const styles = StyleSheet.create({ | |
headerCompContainer: { | |
alignItems: "center", | |
flexDirection: "row", | |
justifyContent: "space-between", | |
marginBottom: 10, | |
width: "100%", | |
}, | |
headerCompText: { | |
color: COLORS.black, | |
fontFamily: "Roboto-Bold", | |
fontSize: 16, | |
}, | |
modalContainer: { | |
backgroundColor: COLORS.white, | |
borderRadius: 12, | |
maxHeight: SCREEN_HEIGHT * 0.85, | |
overflow: "hidden", | |
padding: "3%", | |
}, | |
}); | |
export default memo(TemplateModal); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment