diff --git a/src/lib/msgUtils.js b/src/lib/msgUtils.js
index dcd2b7e..c9710dc 100644
--- a/src/lib/msgUtils.js
+++ b/src/lib/msgUtils.js
@@ -175,7 +175,6 @@ export const whatsappMsgTypeMapped = {
type: 'text',
data: (msg) => {
const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({...r, [v.type]: v}), {}) : null;
- console.log(msg.template.name, templateDataMapped);
return { id: msg.wamid, text: templateDataMapped?.body?.parameters?.[0]?.text || '', title: msg.template.name }
},
},
@@ -226,6 +225,7 @@ export const parseRenderMessageList = (messages, conversationid = null) => {
/**
* WhatsApp Templates params
+ * @deprecated
*/
export const whatsappTemplatesParamMapped = {
/** @deprecated */
diff --git a/src/views/Conversations/ChatWindow.jsx b/src/views/Conversations/ChatWindow.jsx
index 749d26b..fd7605d 100644
--- a/src/views/Conversations/ChatWindow.jsx
+++ b/src/views/Conversations/ChatWindow.jsx
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { Layout, Spin } from 'antd';
import MessagesHeader from './Components/MessagesHeader';
import Messages from './Components/Messages';
-import InputBox from './Components/InputBox';
+import InputBox from './Components/InputComposer';
import ConversationsList from './Components/ConversationsList';
import CustomerProfile from './Components/CustomerProfile';
diff --git a/src/views/Conversations/Components/InputBox.jsx b/src/views/Conversations/Components/InputBox.jsx
deleted file mode 100644
index 19ee899..0000000
--- a/src/views/Conversations/Components/InputBox.jsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { Input, Button, Tabs, List, Space, Popover, Flex } from 'antd';
-// import { Input } from 'react-chat-elements';
-import { useConversationState, useConversationDispatch } from '@/stores/ConversationContext';
-import { sentNewMessage } from '@/actions/ConversationActions';
-import { useAuthContext } from '@/stores/AuthContext';
-import { LikeOutlined, MessageOutlined, StarOutlined, SendOutlined, PlusOutlined, PlusCircleOutlined } from '@ant-design/icons';
-import { cloneDeep, getNestedValue, isEmpty } from '@/utils/utils';
-import { v4 as uuid } from 'uuid';
-import { whatsappTemplatesParamMapped, sentMsgTypeMapped, replaceTemplateString } from '@/lib/msgUtils';
-
-const InputBox = () => {
- const { loginUser } = useAuthContext();
- const { userId } = loginUser;
- const { websocket, currentConversation, templates } = useConversationState();
- const dispatch = useConversationDispatch();
- const [textContent, setTextContent] = useState('');
-
- const talkabled = !isEmpty(currentConversation.sn);
-
- const invokeSendMessage = (msgObj) => {
- console.log('sendMessage------------------', msgObj);
- const contentToSend = sentMsgTypeMapped[msgObj.type].contentToSend(msgObj);
- console.log('content to send-------------------------------------', contentToSend);
- websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn });
- const contentToRender = sentMsgTypeMapped[msgObj.type].contentToRender(msgObj);
- console.log(contentToRender, 'contentToRender sendMessage------------------');
- dispatch(sentNewMessage(contentToRender));
- };
-
- const handleSendText = () => {
- if (textContent.trim() !== '') {
- const msgObj = {
- type: 'text',
- text: textContent,
- sender: 'me',
- to: currentConversation.whatsapp_phone_number,
- id: `${currentConversation.sn}.${uuid()}`, // Date.now().toString(16),
- date: new Date(),
- status: 'waiting',
- };
- invokeSendMessage(msgObj);
- setTextContent('');
- }
- };
-
- const handleSendTemplate = (fromTemplate) => {
- console.log(fromTemplate, 'fromTemplate');
- const _conversation = { ...cloneDeep(currentConversation) };
- const msgObj = {
- type: 'whatsappTemplate',
- to: currentConversation.whatsapp_phone_number,
- id: `${currentConversation.sn}.${uuid()}`,
- date: new Date(),
- status: 'waiting',
- statusTitle: 'Ready to send',
- sender: 'me',
- template: {
- name: fromTemplate.name,
- language: { code: fromTemplate.language },
- components: fromTemplate.components_origin.map(citem => {
- const params = whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) || '' }));
- const paramText = params.map((p) => p.text);
- const fillTemplate = paramText.length ? replaceTemplateString(citem?.text || '', paramText) : citem?.text || '';
-
- return {
- type: citem.type.toLowerCase(),
- parameters: params,
- text: fillTemplate,
- };
- }),
- // ...(fromTemplate.components.body[0]?.example?.body_text?.[0]?.length > 0
- // ? {
- // components: [
- // {
- // 'type': 'body',
- // 'text': fromTemplate.components.body[0]?.text,
- // 'parameters': whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) || '' })),
- // // [
- // // {
- // // 'type': 'text',
- // // 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
- // // },
- // // { // debug:
- // // 'type': 'text',
- // // 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name]?.[1] || whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
- // // },
- // // ],
- // },
- // ],
- // }
- // : {}),
- },
- template_origin: fromTemplate,
- };
- invokeSendMessage(msgObj);
- setOpenTemplates(false);
- };
-
- const [openTemplates, setOpenTemplates] = useState(false);
- const handleOpenChange = (newOpen) => {
- setOpenTemplates(newOpen);
- };
- return (
-
-
- (
-
-
- <>{item.components.header?.[0]?.text || item.name}>
-
-
- }
- description={item.components.body?.[0]?.text}
- />
-
- )}
- />
- }
- title='🙋打招呼'
- trigger='click'
- open={openTemplates}
- onOpenChange={handleOpenChange}>
-
} size={'large'} disabled={!talkabled} />
-
-
}
- size='large'
- onSearch={handleSendText}
- value={textContent}
- onChange={(e) => setTextContent(e.target.value)}
- />
-
-
-
- );
-};
-
-export default InputBox;
diff --git a/src/views/Conversations/Components/InputComposer.jsx b/src/views/Conversations/Components/InputComposer.jsx
new file mode 100644
index 0000000..3c6a0b4
--- /dev/null
+++ b/src/views/Conversations/Components/InputComposer.jsx
@@ -0,0 +1,68 @@
+import React, { useState } from 'react';
+import { Input, Flex } from 'antd';
+// import { Input } from 'react-chat-elements';
+import { useConversationState, useConversationDispatch } from '@/stores/ConversationContext';
+import { useAuthContext } from '@/stores/AuthContext';
+import { sentNewMessage } from '@/actions/ConversationActions';
+import { SendOutlined } from '@ant-design/icons';
+import { isEmpty } from '@/utils/utils';
+import { v4 as uuid } from 'uuid';
+import { sentMsgTypeMapped } from '@/lib/msgUtils';
+import InputTemplate from './InputTemplate';
+
+const InputBox = () => {
+ const { loginUser } = useAuthContext();
+ const { userId } = loginUser;
+ const { websocket, currentConversation, } = useConversationState();
+ const dispatch = useConversationDispatch();
+ const [textContent, setTextContent] = useState('');
+
+ const talkabled = !isEmpty(currentConversation.sn);
+
+ const invokeSendMessage = (msgObj) => {
+ console.log('sendMessage------------------', msgObj);
+ const contentToSend = sentMsgTypeMapped[msgObj.type].contentToSend(msgObj);
+ console.log('content to send-------------------------------------', contentToSend);
+ websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn });
+ const contentToRender = sentMsgTypeMapped[msgObj.type].contentToRender(msgObj);
+ console.log(contentToRender, 'contentToRender sendMessage------------------');
+ dispatch(sentNewMessage(contentToRender));
+ };
+
+ const handleSendText = () => {
+ if (textContent.trim() !== '') {
+ const msgObj = {
+ type: 'text',
+ text: textContent,
+ sender: 'me',
+ to: currentConversation.whatsapp_phone_number,
+ id: `${currentConversation.sn}.${uuid()}`, // Date.now().toString(16),
+ date: new Date(),
+ status: 'waiting',
+ };
+ invokeSendMessage(msgObj);
+ setTextContent('');
+ }
+ };
+
+ return (
+
+
+
+ }
+ size='large'
+ onSearch={handleSendText}
+ value={textContent}
+ onChange={(e) => setTextContent(e.target.value)}
+ />
+
+
+
+ );
+};
+
+export default InputBox;
diff --git a/src/views/Conversations/Components/InputTemplate.jsx b/src/views/Conversations/Components/InputTemplate.jsx
new file mode 100644
index 0000000..80955b1
--- /dev/null
+++ b/src/views/Conversations/Components/InputTemplate.jsx
@@ -0,0 +1,149 @@
+import { useState } from 'react';
+import { App, Popover, Flex, Button, List, Input } from 'antd';
+import { MessageOutlined, SendOutlined } from '@ant-design/icons';
+import { useAuthContext } from '@/stores/AuthContext';
+import { useConversationState } from '@/stores/ConversationContext';
+import { cloneDeep, flush, getNestedValue, objectMapper } from '@/utils/utils';
+import { v4 as uuid } from 'uuid';
+import { replaceTemplateString } from '@/lib/msgUtils';
+
+const splitTemplate = (template) => {
+ const placeholders = template.match(/{{(.*?)}}/g) || [];
+ const keys = placeholders.map((placeholder) => placeholder.slice(2, -2));
+ const arr = template.split(/{{(.*?)}}/).filter(Boolean);
+ const obj = arr.reduce((prev, curr, index) => {
+ if (keys.includes(curr)) {
+ prev.push({ key: curr });
+ } else {
+ prev.push(curr);
+ }
+ return prev;
+ }, []);
+ return obj;
+};
+const InputTemplate = ({ disabled = false, invokeSendMessage }) => {
+ const { notification } = App.useApp()
+ const { loginUser } = useAuthContext();
+ const { currentConversation, templates } = useConversationState();
+ // 用于替换变量: customer, agent
+ const valueMapped = { ...cloneDeep(currentConversation), ...objectMapper(loginUser, { username: [{ key: 'agent_name' }, { key: 'your_name' }] }) };
+
+ const [openTemplates, setOpenTemplates] = useState(false);
+ const handleOpenChange = (newOpen) => {
+ setOpenTemplates(newOpen);
+ };
+ const handleSendTemplate = (fromTemplate) => {
+ const mergeInput = {...cloneDeep(valueMapped), ...activeInput[fromTemplate.name]};
+ let valid = true;
+ const msgObj = {
+ type: 'whatsappTemplate',
+ to: currentConversation.whatsapp_phone_number,
+ id: `${currentConversation.sn}.${uuid()}`,
+ date: new Date(),
+ status: 'waiting',
+ // statusTitle: 'Ready to send',
+ sender: 'me',
+ template: {
+ name: fromTemplate.name,
+ language: { code: fromTemplate.language },
+ components: fromTemplate.components_origin.map((citem) => {
+ const keys = (citem?.text || '').match(/{{(.*?)}}/g).map((key) => key.replace(/{{|}}/g, ''));
+ const params = keys.map((v) => ({ type: 'text', text: getNestedValue(mergeInput, [v]) }));
+ const paramText = params.map((p) => p.text);
+ const fillTemplate = paramText.length ? replaceTemplateString(citem?.text || '', paramText) : citem?.text || '';
+ valid = keys.length !== flush(paramText).length ? false : valid;
+ return {
+ type: citem.type.toLowerCase(),
+ parameters: params,
+ text: fillTemplate,
+ };
+ }),
+ },
+ template_origin: fromTemplate,
+ };
+ if (valid !== true) {
+ notification.warning({
+ message: '提示',
+ description: '信息未填写完整, 请补充填写',
+ placement: 'top',
+ duration: 3,
+ })
+ return false;
+ }
+ invokeSendMessage(msgObj);
+ setOpenTemplates(false);
+ };
+
+ const [activeInput, setActiveInput] = useState({});
+ const onInput = (tempItem, key, val, initObj) => {
+ setActiveInput((prev) => {
+ return { ...prev, [tempItem.name]: { ...initObj, ...prev[tempItem.name], [key]: val } };
+ });
+ };
+
+ const renderForm = (tempItem) => {
+ const templateText = tempItem.components.body?.[0]?.text || '';
+ const tempArr = splitTemplate(templateText);
+ const keys = templateText.match(/{{(.*?)}}/g).map((key) => key.replace(/{{|}}/g, ''));
+ const paramsVal = keys.reduce((r, k) => ({ ...r, [k]: getNestedValue(valueMapped, [k]) }), {});
+
+ return tempArr.map((ele) =>
+ typeof ele === 'string' ? (
+
+ {ele}
+
+ ) : (
+ onInput(tempItem, ele.key, e.target.value, paramsVal)}
+ className='w-auto max-w-24'
+ size={'small'}
+ title={ele.key}
+ placeholder={paramsVal[ele.key] || ele.key}
+ />
+ )
+ );
+ };
+ return (
+ <>
+ (
+
+
+ <>{item.components.header?.[0]?.text || item.name}>
+
+
+ }
+ description={
+ <>
+
+
{renderForm(item)}
+ {item.components?.footer?.[0] ?
{item.components.footer[0].text || ''}
: null}
+
+ >
+ }
+ />
+
+ )}
+ />
+ }
+ title='🙋打招呼'
+ trigger='click'
+ open={openTemplates}
+ onOpenChange={handleOpenChange}>
+ } size={'large'} disabled={disabled} />
+
+ >
+ );
+};
+export default InputTemplate;