@clikvn/agent-widget-embedded 1.1.5-dev-14 → 1.1.5-dev-16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Chat.js +2 -2
  2. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Chat.js.map +1 -1
  3. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Message.d.ts +3 -3
  4. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Message.d.ts.map +1 -1
  5. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Message.js +4 -3
  6. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Message.js.map +1 -1
  7. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductDetail.d.ts +0 -2
  8. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductDetail.d.ts.map +1 -1
  9. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductDetail.js +6 -55
  10. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductDetail.js.map +1 -1
  11. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductList.d.ts +1 -7
  12. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductList.d.ts.map +1 -1
  13. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductList.js +2 -61
  14. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ProductList.js.map +1 -1
  15. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ScenariosList.d.ts +1 -12
  16. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ScenariosList.d.ts.map +1 -1
  17. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ScenariosList.js +3 -18
  18. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/ScenariosList.js.map +1 -1
  19. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.d.ts +22 -0
  20. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.d.ts.map +1 -0
  21. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.js +301 -0
  22. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.js.map +1 -0
  23. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/constants/toolNames.d.ts +2 -9
  24. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/constants/toolNames.d.ts.map +1 -1
  25. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/constants/toolNames.js +2 -8
  26. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/constants/toolNames.js.map +1 -1
  27. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/features/AgentWidget/index.d.ts +1 -0
  28. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/features/AgentWidget/index.d.ts.map +1 -1
  29. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/features/AgentWidget/index.js.map +1 -1
  30. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/hooks/useScrollToBottom.d.ts +2 -4
  31. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/hooks/useScrollToBottom.d.ts.map +1 -1
  32. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/hooks/useScrollToBottom.js +3 -38
  33. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/hooks/useScrollToBottom.js.map +1 -1
  34. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/utils/toolUtils.d.ts.map +1 -1
  35. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/utils/toolUtils.js +15 -7
  36. package/.rollup.cache/Users/tungthai/Desktop/Develop/clik-ai-chatbot-embedded/dist/utils/toolUtils.js.map +1 -1
  37. package/dist/components/Chat/Message.d.ts +3 -3
  38. package/dist/components/Chat/Message.d.ts.map +1 -1
  39. package/dist/components/Chat/ProductDetail.d.ts +0 -2
  40. package/dist/components/Chat/ProductDetail.d.ts.map +1 -1
  41. package/dist/components/Chat/ProductList.d.ts +1 -7
  42. package/dist/components/Chat/ProductList.d.ts.map +1 -1
  43. package/dist/components/Chat/ScenariosList.d.ts +1 -12
  44. package/dist/components/Chat/ScenariosList.d.ts.map +1 -1
  45. package/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.d.ts +22 -0
  46. package/dist/components/Chat/Simplified/MultimodalInputSimplifiedOld.d.ts.map +1 -0
  47. package/dist/constants/toolNames.d.ts +2 -9
  48. package/dist/constants/toolNames.d.ts.map +1 -1
  49. package/dist/index.html +3 -3
  50. package/dist/utils/toolUtils.d.ts.map +1 -1
  51. package/dist/web.js +1 -1
  52. package/dist/web.js.map +1 -1
  53. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { PreviewMessage, ThinkingMessage } from './Message';
3
+ import PreviewMessage, { ThinkingMessage } from './Message';
4
4
  import { useChat } from '../../hooks/useChat';
5
5
  import { useScrollContainer } from '../../hooks/useScrollContainer';
6
6
  import { MultimodalInput } from './MultimodalInput';
@@ -40,6 +40,6 @@ export const Chat = ({ id, agentId, initialMessages = [] }) => {
40
40
  e.preventDefault();
41
41
  e.stopPropagation();
42
42
  scrollToTop();
43
- }, className: "absolute w-[28px] h-[28px] left-[50%] top-[16px] z-50 bg-white shadow-lg rounded-full flex items-center justify-center hover:bg-gray-50 transition-colors", "aria-label": "Scroll to top", children: _jsx(ArrowUp, { size: 16, className: "text-zinc-900" }) })) }), _jsx("form", { className: "flex mx-auto px-4 bg-background pb-4 gap-2 w-full md:max-w-3xl", children: _jsx(MultimodalInput, { input: input, setInput: setInput, chatId: chatId, handleSubmit: handleSubmit, isLoading: isLoading, stop: stop, messages: messages, setMessages: setMessages, append: append, attachments: attachments, setAttachments: setAttachments, bot: bot, apiHost: apiHost, setEnableTTS: setEnableTTS, enableTTS: enableTTS, suggestedActions: suggestions }) })] }) }));
43
+ }, className: "absolute w-[28px] h-[28px] left-[50%] top-[16px] z-50 bg-white shadow-lg rounded-full flex items-center justify-center hover:bg-gray-50 transition-colors", "aria-label": "Scroll to top", children: _jsx(ArrowUp, { size: 16, className: "text-zinc-900" }) })) }), _jsx("form", { className: "flex mx-auto px-4 bg-background pb-4 gap-2 w-full md:max-w-3xl", children: _jsx(MultimodalInput, { input: input, setInput: setInput, chatId: chatId, handleSubmit: handleSubmit, isLoading: isLoading, stop: stop, messages: messages, setMessages: setMessages, append: append, attachments: attachments, setAttachments: setAttachments, bot: bot, apiHost: apiHost, setEnableTTS: setEnableTTS, enableTTS: enableTTS, suggestedActions: suggestions }) })] }) }));
44
44
  };
45
45
  //# sourceMappingURL=Chat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/components/Chat/Chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useState } from 'react';\nimport { ChatMessageType, IFileUpload } from '../../types/flowise.type';\nimport { PreviewMessage, ThinkingMessage } from './Message';\nimport { useChat } from '../../hooks/useChat';\nimport { useScrollContainer } from '../../hooks/useScrollContainer';\nimport { MultimodalInput } from './MultimodalInput';\nimport { Overview } from './Overview';\nimport { useConfiguration } from '../../hooks/useConfiguration';\nimport { MenuIcon } from './Icons';\nimport {\n DropdownMenu,\n DropdownMenuItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from './ui/DropdownMenu';\nimport { useChatData } from 'hooks/useChatData';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { ArrowUp } from 'lucide-react';\n\ntype PropsType = {\n id?: string;\n initialMessages?: ChatMessageType[];\n agentId?: string;\n};\n\nexport const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {\n const {\n messages = [],\n setMessages,\n handleSubmit,\n input = '',\n setInput,\n isLoading,\n stop,\n chatId,\n append,\n bot,\n enableTTS,\n setEnableTTS,\n suggestions,\n } = useChat({ id, initialMessages, agentId });\n const { apiHost } = useConfiguration();\n const [messagesContainerRef, messagesEndRef, , showScrollToTop, scrollToTop] =\n useScrollContainer<HTMLDivElement>();\n const [attachments, setAttachments] = useState<Array<IFileUpload>>([]);\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const { listeners, createNew } = useChatData();\n\n const handleCreateNewChat = (e: React.MouseEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n let id: string = '';\n if (createNew) {\n id = createNew();\n }\n if (listeners?.['ON_NEW_CHAT']) {\n listeners['ON_NEW_CHAT'](id);\n }\n // Đóng dropdown sau khi tạo chat mới\n setDropdownOpen(false);\n };\n\n const hasMessages = (messages?.length || 0) > 0;\n const isThinking =\n isLoading &&\n hasMessages &&\n messages[messages.length - 1].role === 'userMessage';\n\n return (\n <>\n <div className=\"flex flex-col min-w-0 h-full relative bg-background\">\n {/* <Header title={theme?.header?.title} language={language} /> */}\n <div className=\"absolute left-4 top-4 z-10\">\n <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>\n <DropdownMenuTrigger className=\"outline-none\">\n <div className=\"w-10 h-[40px] shadow-sm flex items-center justify-center p-1 bg-white rounded-full outline-none\">\n <MenuIcon size={20} />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent side=\"right\">\n <DropdownMenuItem>\n <div onClick={handleCreateNewChat}>New chat</div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n <div\n ref={messagesContainerRef}\n className=\"flex flex-col min-w-0 gap-[16px] flex-1 overflow-y-scroll pt-[16px]\"\n >\n {!hasMessages && <Overview bot={bot} />}\n\n {hasMessages &&\n messages.map((message, index) => (\n <PreviewMessage\n key={message.id}\n bot={bot}\n chatId={id}\n message={message}\n isLoading={isLoading && (messages || []).length - 1 === index}\n enableTTS={enableTTS}\n />\n ))}\n {isThinking && <ThinkingMessage bot={bot} />}\n\n <div\n ref={messagesEndRef}\n className=\"shrink-0 min-w-[24px] min-h-[24px]\"\n />\n </div>\n\n {/* Scroll to Top Button */}\n <AnimatePresence>\n {showScrollToTop && (\n <motion.button\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.8 }}\n transition={{ duration: 0.2 }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n scrollToTop();\n }}\n className=\"absolute w-[28px] h-[28px] left-[50%] top-[16px] z-50 bg-white shadow-lg rounded-full flex items-center justify-center hover:bg-gray-50 transition-colors\"\n aria-label=\"Scroll to top\"\n >\n <ArrowUp size={16} className=\"text-zinc-900\" />\n </motion.button>\n )}\n </AnimatePresence>\n\n <form className=\"flex mx-auto px-4 bg-background pb-4 gap-2 w-full md:max-w-3xl\">\n <MultimodalInput\n input={input}\n setInput={setInput}\n chatId={chatId}\n handleSubmit={handleSubmit}\n isLoading={isLoading}\n stop={stop}\n messages={messages}\n setMessages={setMessages}\n append={append}\n attachments={attachments}\n setAttachments={setAttachments}\n bot={bot}\n apiHost={apiHost}\n setEnableTTS={setEnableTTS}\n enableTTS={enableTTS}\n suggestedActions={suggestions}\n />\n </form>\n </div>\n </>\n );\n};\n"]}
1
+ {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/components/Chat/Chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useState } from 'react';\nimport { ChatMessageType, IFileUpload } from '../../types/flowise.type';\nimport PreviewMessage, { ThinkingMessage } from './Message';\nimport { useChat } from '../../hooks/useChat';\nimport { useScrollContainer } from '../../hooks/useScrollContainer';\nimport { MultimodalInput } from './MultimodalInput';\nimport { Overview } from './Overview';\nimport { useConfiguration } from '../../hooks/useConfiguration';\nimport { MenuIcon } from './Icons';\nimport {\n DropdownMenu,\n DropdownMenuItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from './ui/DropdownMenu';\nimport { useChatData } from 'hooks/useChatData';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { ArrowUp } from 'lucide-react';\n\ntype PropsType = {\n id?: string;\n initialMessages?: ChatMessageType[];\n agentId?: string;\n};\n\nexport const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {\n const {\n messages = [],\n setMessages,\n handleSubmit,\n input = '',\n setInput,\n isLoading,\n stop,\n chatId,\n append,\n bot,\n enableTTS,\n setEnableTTS,\n suggestions,\n } = useChat({ id, initialMessages, agentId });\n const { apiHost } = useConfiguration();\n const [messagesContainerRef, messagesEndRef, , showScrollToTop, scrollToTop] =\n useScrollContainer<HTMLDivElement>();\n const [attachments, setAttachments] = useState<Array<IFileUpload>>([]);\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const { listeners, createNew } = useChatData();\n\n const handleCreateNewChat = (e: React.MouseEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n let id: string = '';\n if (createNew) {\n id = createNew();\n }\n if (listeners?.['ON_NEW_CHAT']) {\n listeners['ON_NEW_CHAT'](id);\n }\n // Đóng dropdown sau khi tạo chat mới\n setDropdownOpen(false);\n };\n\n const hasMessages = (messages?.length || 0) > 0;\n const isThinking =\n isLoading &&\n hasMessages &&\n messages[messages.length - 1].role === 'userMessage';\n\n return (\n <>\n <div className=\"flex flex-col min-w-0 h-full relative bg-background\">\n {/* <Header title={theme?.header?.title} language={language} /> */}\n <div className=\"absolute left-4 top-4 z-10\">\n <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>\n <DropdownMenuTrigger className=\"outline-none\">\n <div className=\"w-10 h-[40px] shadow-sm flex items-center justify-center p-1 bg-white rounded-full outline-none\">\n <MenuIcon size={20} />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent side=\"right\">\n <DropdownMenuItem>\n <div onClick={handleCreateNewChat}>New chat</div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n <div\n ref={messagesContainerRef}\n className=\"flex flex-col min-w-0 gap-[16px] flex-1 overflow-y-scroll pt-[16px]\"\n >\n {!hasMessages && <Overview bot={bot} />}\n\n {hasMessages &&\n messages.map((message, index) => (\n <PreviewMessage\n key={message.id}\n bot={bot}\n chatId={id}\n message={message}\n isLoading={isLoading && (messages || []).length - 1 === index}\n enableTTS={enableTTS}\n />\n ))}\n {isThinking && <ThinkingMessage bot={bot} />}\n\n <div\n ref={messagesEndRef}\n className=\"shrink-0 min-w-[24px] min-h-[24px]\"\n />\n </div>\n\n {/* Scroll to Top Button */}\n <AnimatePresence>\n {showScrollToTop && (\n <motion.button\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.8 }}\n transition={{ duration: 0.2 }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n scrollToTop();\n }}\n className=\"absolute w-[28px] h-[28px] left-[50%] top-[16px] z-50 bg-white shadow-lg rounded-full flex items-center justify-center hover:bg-gray-50 transition-colors\"\n aria-label=\"Scroll to top\"\n >\n <ArrowUp size={16} className=\"text-zinc-900\" />\n </motion.button>\n )}\n </AnimatePresence>\n\n <form className=\"flex mx-auto px-4 bg-background pb-4 gap-2 w-full md:max-w-3xl\">\n <MultimodalInput\n input={input}\n setInput={setInput}\n chatId={chatId}\n handleSubmit={handleSubmit}\n isLoading={isLoading}\n stop={stop}\n messages={messages}\n setMessages={setMessages}\n append={append}\n attachments={attachments}\n setAttachments={setAttachments}\n bot={bot}\n apiHost={apiHost}\n setEnableTTS={setEnableTTS}\n enableTTS={enableTTS}\n suggestedActions={suggestions}\n />\n </form>\n </div>\n </>\n );\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { FC } from 'react';
1
+ import React from 'react';
2
2
  import { BotType } from '../../types/bot.type';
3
3
  import { ChatMessageType } from '../../types/flowise.type';
4
4
  type PropsType = {
@@ -8,9 +8,9 @@ type PropsType = {
8
8
  bot: BotType | null;
9
9
  enableTTS?: boolean;
10
10
  };
11
- export declare const PreviewMessage: FC<PropsType>;
12
11
  export declare const ThinkingMessage: ({ bot }: {
13
12
  bot: BotType | null;
14
13
  }) => import("react/jsx-runtime").JSX.Element;
15
- export {};
14
+ declare const _default: React.NamedExoticComponent<PropsType>;
15
+ export default _default;
16
16
  //# sourceMappingURL=Message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/Message.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAsB,MAAM,OAAO,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAa,MAAM,0BAA0B,CAAC;AAoCtE,KAAK,SAAS,GAAG;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,SAAS,CA8LxC,CAAC;AAEF,eAAO,MAAM,eAAe,YAAa;IAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,4CAyC/D,CAAC"}
1
+ {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/Message.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAiC,MAAM,OAAO,CAAC;AAGtD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAa,MAAM,0BAA0B,CAAC;AAoCtE,KAAK,SAAS,GAAG;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AA+LF,eAAO,MAAM,eAAe,YAAa;IAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,4CAyC/D,CAAC;;AAEF,wBAA0C"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { motion } from 'framer-motion';
3
3
  import { useConfiguration } from 'hooks/useConfiguration';
4
- import { useEffect, useMemo } from 'react';
4
+ import React, { useEffect, useMemo } from 'react';
5
5
  import { LOCATION_TOOLS } from '../../constants/toolNames';
6
6
  import { useChatData } from '../../hooks/useChatData';
7
7
  import { cn } from '../../utils/commonUtils';
@@ -20,7 +20,7 @@ import ProductList from './ProductList';
20
20
  import { ScenariosList } from './ScenariosList';
21
21
  import UserContactForm from './UserContactForm';
22
22
  import { Weather } from './Weather';
23
- export const PreviewMessage = ({ chatId, message, bot, enableTTS, isLoading, }) => {
23
+ const PreviewMessage = ({ chatId, message, bot, enableTTS, isLoading, }) => {
24
24
  const { theme, overrideConfig } = useConfiguration();
25
25
  const { listeners } = useChatData();
26
26
  const usedTools = useMemo(() => {
@@ -59,7 +59,7 @@ export const PreviewMessage = ({ chatId, message, bot, enableTTS, isLoading, })
59
59
  const outputData = parseToolOutput(toolOutput);
60
60
  return (_jsxs("div", { className: "custom-tool-result", children: [!!outputData && isWeatherTool(tool) && (_jsx(Weather, { weatherAtLocation: outputData })), !!outputData?.data?.getCMSLocationInfoDetail &&
61
61
  tool === LOCATION_TOOLS.GET_ASSIGNED_LOCATION_DETAIL && (_jsx(LocationCard, { location: outputData.data.getCMSLocationInfoDetail })), !!outputData &&
62
- tool === LOCATION_TOOLS.SEARCH_TRAVELING_PLACES && (_jsx("div", { className: "flex flex-row overflow-x-auto", children: outputData.map((place) => (_jsx("div", { className: "flex-shrink-0 pr-2 max-w-full", children: _jsx(LocationCard, { location: place }) }, place.id))) })), !!toolOutput && isDisplayProductListTool(tool) && (_jsx(ProductList, { content: outputData || toolOutput, productCodesStr: toolInput?.productCodes, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayScenariosTool(tool) && (_jsx(ScenariosList, { content: outputData, scenarioCodesStr: toolInput?.scenarioCodes, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayProductDetailTool(tool) && (_jsx(ProductDetail, { content: outputData, productCode: toolInput?.productCode, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayBookingFormTool(tool) && (_jsx(BookMeetingForm, {})), !!toolOutput && isDisplayContactFormTool(tool) && (_jsx(UserContactForm, {})), !!toolOutput && isHtmlContent(usedTool) && (_jsx(HtmlContent, { content: outputData.content }))] }, `${tool}-${index}`));
62
+ tool === LOCATION_TOOLS.SEARCH_TRAVELING_PLACES && (_jsx("div", { className: "flex flex-row overflow-x-auto", children: outputData.map((place) => (_jsx("div", { className: "flex-shrink-0 pr-2 max-w-full", children: _jsx(LocationCard, { location: place }) }, place.id))) })), !!toolOutput && isDisplayProductListTool(tool) && (_jsx(ProductList, { productCodes: outputData.product_codes, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayProductDetailTool(tool) && (_jsx(ProductDetail, { productCode: outputData.product_code, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayScenariosTool(tool) && (_jsx(ScenariosList, { scenarioCodes: outputData?.scenario_codes, tourCode: overrideConfig?.vars?.TOUR_CODE, languageCode: overrideConfig?.vars?.LANGUAGE_CODE, apiUrl: overrideConfig?.vars?.CLIK_GRAPHQL_API })), !!toolOutput && isDisplayBookingFormTool(tool) && (_jsx(BookMeetingForm, {})), !!toolOutput && isDisplayContactFormTool(tool) && (_jsx(UserContactForm, {})), !!toolOutput && isHtmlContent(usedTool) && (_jsx(HtmlContent, { content: outputData.content }))] }, `${tool}-${index}`));
63
63
  }) }))] })] })] }));
64
64
  };
65
65
  export const ThinkingMessage = ({ bot }) => {
@@ -70,4 +70,5 @@ export const ThinkingMessage = ({ bot }) => {
70
70
  'group-data-[role=user]/message:bg-muted': true,
71
71
  }), children: [shouldShowAvatar(theme, 'apiMessage') && (_jsx("div", { className: "size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border", children: _jsx("img", { src: assistantAvatar, alt: bot?.name ?? 'User Avatar', width: 24, height: 24, className: "rounded-full" }) })), _jsx("div", { className: "flex flex-col gap-2 w-full", children: _jsx("div", { className: "flex flex-col gap-4 text-muted-foreground", children: "Thinking..." }) })] }) }));
72
72
  };
73
+ export default React.memo(PreviewMessage);
73
74
  //# sourceMappingURL=Message.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Message.js","sourceRoot":"","sources":["../../../src/components/Chat/Message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { motion } from 'framer-motion';\nimport { useConfiguration } from 'hooks/useConfiguration';\nimport { FC, useEffect, useMemo } from 'react';\nimport { LOCATION_TOOLS } from '../../constants/toolNames';\nimport { useChatData } from '../../hooks/useChatData';\nimport { BotType } from '../../types/bot.type';\nimport { ChatMessageType, ToolUsage } from '../../types/flowise.type';\nimport { cn } from '../../utils/commonUtils';\nimport {\n getAvatarSource,\n getMessageBackgroundColor,\n getMessageTextColor,\n getRole,\n shouldShowAvatar,\n} from '../../utils/messageUtils';\nimport {\n categorizeTools,\n hasFocusToolOutput,\n isDisplayBookingFormTool,\n isDisplayContactFormTool,\n isDisplayProductDetailTool,\n isDisplayProductListTool,\n isDisplayScenariosTool,\n isHtmlContent,\n isWeatherTool,\n parseToolOutput,\n removeToolOutputFromContent,\n} from '../../utils/toolUtils';\nimport AgentThinking from './AgentThinking';\nimport AudioPlayer from './AudioPlayer';\nimport BookMeetingForm from './BookMeetingForm';\nimport { HtmlContent } from './HtmlContent';\nimport { SparklesIcon } from './Icons';\nimport { LocationCard } from './LocationCard';\nimport { Markdown } from './Markdown';\nimport { PreviewAttachment } from './PreviewAttachment';\nimport ProductDetail from './ProductDetail';\nimport ProductList from './ProductList';\nimport { ScenariosList } from './ScenariosList';\nimport UserContactForm from './UserContactForm';\nimport { Weather } from './Weather';\n\ntype PropsType = {\n chatId?: string;\n message: ChatMessageType;\n isLoading: boolean;\n bot: BotType | null;\n enableTTS?: boolean;\n};\n\nexport const PreviewMessage: FC<PropsType> = ({\n chatId,\n message,\n bot,\n enableTTS,\n isLoading,\n}) => {\n const { theme, overrideConfig } = useConfiguration();\n const { listeners } = useChatData();\n\n const usedTools = useMemo(() => {\n return categorizeTools(message.usedTools || [], !!message.new);\n }, [message.usedTools, message.new]);\n\n const role = useMemo(() => {\n return getRole(message.role);\n }, [message.role]);\n\n const assistantAvatar = getAvatarSource(role, theme, bot?.avatar);\n\n const focusToolOutput = useMemo(() => {\n return hasFocusToolOutput(message.usedTools || []);\n }, [message.usedTools]);\n\n const messageContent = useMemo(() => {\n if (!focusToolOutput) {\n return message.content;\n }\n\n return removeToolOutputFromContent(\n message.content,\n message.usedTools || []\n );\n }, [focusToolOutput, message.content, message.usedTools]);\n\n useEffect(() => {\n const cmdTool = usedTools?.cmdToolResult as any;\n if (!cmdTool || !listeners?.['CMD_CALLBACK']) {\n return;\n }\n\n const tool = cmdTool as ToolUsage;\n listeners['CMD_CALLBACK']({\n tool: tool.tool,\n output: tool.toolOutput,\n });\n }, [usedTools]);\n\n return (\n <motion.div\n className=\"w-full mx-auto max-w-3xl px-4 group/message\"\n initial={{ y: 5, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n data-role={role}\n >\n <div className=\"flex justify-end text-[14px]\">\n {message?.fileUploads && !!message.fileUploads.length && (\n <PreviewAttachment attachment={message.fileUploads[0]} />\n )}\n </div>\n <div\n className={cn(\n `group-data-[role=user]/message:bg-[#FFF] group-data-[role=user]/message:rounded-[24px] text-[#18181B] group-data-[role=user]/message:px-[16px] group-data-[role=user]/message:py-[10px] flex gap-4 w-full group-data-[role=user]/message:w-fit group-data-[role=user]/message:ml-auto group-data-[role=user]/message:max-w-2xl overflow-x-hidden break-all`\n )}\n style={{\n backgroundColor: getMessageBackgroundColor(role, theme),\n }}\n >\n {shouldShowAvatar(theme, message.role) && (\n <div className=\"size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border\">\n {assistantAvatar ? (\n <img\n src={assistantAvatar}\n alt={bot?.name ?? 'User Avatar'}\n width={24}\n height={24}\n className=\"rounded-full\"\n />\n ) : (\n <SparklesIcon size={14} />\n )}\n </div>\n )}\n\n <div className=\"flex flex-col gap-2 w-full\">\n {/* Agent Thinking Display */}\n {message?.agentSteps && !!message.agentSteps.length && (\n <AgentThinking steps={message.agentSteps} isLoading={isLoading} />\n )}\n\n {/* Message Content */}\n {!!messageContent && (\n <div\n className=\"flex flex-col gap-4\"\n style={{\n color: getMessageTextColor(role, theme),\n }}\n >\n <Markdown\n usedTools={focusToolOutput ? undefined : message?.usedTools}\n >\n {messageContent as string}\n </Markdown>\n </div>\n )}\n\n {/* Audio Player */}\n {!focusToolOutput && (role === 'assistant' || message?.ttsUrl) && (\n <AudioPlayer\n chatId={chatId}\n message={message}\n autoplay={!!enableTTS}\n />\n )}\n\n {/* Custom Tool Results */}\n {!!usedTools?.customToolResults?.length && (\n <div className=\"flex flex-col gap-4 custom-tools\">\n {usedTools.customToolResults.map((usedTool, index) => {\n const { tool, toolOutput, toolInput } = usedTool;\n const outputData = parseToolOutput(toolOutput);\n return (\n <div key={`${tool}-${index}`} className=\"custom-tool-result\">\n {!!outputData && isWeatherTool(tool) && (\n <Weather weatherAtLocation={outputData} />\n )}\n {!!outputData?.data?.getCMSLocationInfoDetail &&\n tool === LOCATION_TOOLS.GET_ASSIGNED_LOCATION_DETAIL && (\n <LocationCard\n location={outputData.data.getCMSLocationInfoDetail}\n />\n )}\n {!!outputData &&\n tool === LOCATION_TOOLS.SEARCH_TRAVELING_PLACES && (\n <div className=\"flex flex-row overflow-x-auto\">\n {outputData.map((place: any) => (\n <div\n key={place.id}\n className=\"flex-shrink-0 pr-2 max-w-full\"\n >\n <LocationCard location={place} />\n </div>\n ))}\n </div>\n )}\n {!!toolOutput && isDisplayProductListTool(tool) && (\n <ProductList\n content={outputData || toolOutput}\n productCodesStr={(toolInput as any)?.productCodes}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayScenariosTool(tool) && (\n <ScenariosList\n content={outputData}\n scenarioCodesStr={(toolInput as any)?.scenarioCodes}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayProductDetailTool(tool) && (\n <ProductDetail\n content={outputData}\n productCode={(toolInput as any)?.productCode}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayBookingFormTool(tool) && (\n <BookMeetingForm />\n )}\n {!!toolOutput && isDisplayContactFormTool(tool) && (\n <UserContactForm />\n )}\n {!!toolOutput && isHtmlContent(usedTool) && (\n <HtmlContent content={outputData.content} />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </motion.div>\n );\n};\n\nexport const ThinkingMessage = ({ bot }: { bot: BotType | null }) => {\n const role = 'assistant';\n\n const { theme } = useConfiguration();\n\n const assistantAvatar = getAvatarSource(role, theme, bot?.avatar);\n\n return (\n <motion.div\n className=\"w-full mx-auto max-w-3xl px-4 group/message\"\n initial={{ y: 5, opacity: 0 }}\n animate={{ y: 0, opacity: 1, transition: { delay: 1 } }}\n data-role={role}\n >\n <div\n className={cn(\n 'flex gap-4 group-data-[role=user]/message:px-3 w-full group-data-[role=user]/message:w-fit group-data-[role=user]/message:ml-auto group-data-[role=user]/message:max-w-2xl group-data-[role=user]/message:py-2 rounded-xl',\n {\n 'group-data-[role=user]/message:bg-muted': true,\n }\n )}\n >\n {shouldShowAvatar(theme, 'apiMessage') && (\n <div className=\"size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border\">\n <img\n src={assistantAvatar}\n alt={bot?.name ?? 'User Avatar'}\n width={24}\n height={24}\n className=\"rounded-full\"\n />\n </div>\n )}\n <div className=\"flex flex-col gap-2 w-full\">\n <div className=\"flex flex-col gap-4 text-muted-foreground\">\n Thinking...\n </div>\n </div>\n </div>\n </motion.div>\n );\n};\n"]}
1
+ {"version":3,"file":"Message.js","sourceRoot":"","sources":["../../../src/components/Chat/Message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { motion } from 'framer-motion';\nimport { useConfiguration } from 'hooks/useConfiguration';\nimport React, { FC, useEffect, useMemo } from 'react';\nimport { LOCATION_TOOLS } from '../../constants/toolNames';\nimport { useChatData } from '../../hooks/useChatData';\nimport { BotType } from '../../types/bot.type';\nimport { ChatMessageType, ToolUsage } from '../../types/flowise.type';\nimport { cn } from '../../utils/commonUtils';\nimport {\n getAvatarSource,\n getMessageBackgroundColor,\n getMessageTextColor,\n getRole,\n shouldShowAvatar,\n} from '../../utils/messageUtils';\nimport {\n categorizeTools,\n hasFocusToolOutput,\n isDisplayBookingFormTool,\n isDisplayContactFormTool,\n isDisplayProductDetailTool,\n isDisplayProductListTool,\n isDisplayScenariosTool,\n isHtmlContent,\n isWeatherTool,\n parseToolOutput,\n removeToolOutputFromContent,\n} from '../../utils/toolUtils';\nimport AgentThinking from './AgentThinking';\nimport AudioPlayer from './AudioPlayer';\nimport BookMeetingForm from './BookMeetingForm';\nimport { HtmlContent } from './HtmlContent';\nimport { SparklesIcon } from './Icons';\nimport { LocationCard } from './LocationCard';\nimport { Markdown } from './Markdown';\nimport { PreviewAttachment } from './PreviewAttachment';\nimport ProductDetail from './ProductDetail';\nimport ProductList from './ProductList';\nimport { ScenariosList } from './ScenariosList';\nimport UserContactForm from './UserContactForm';\nimport { Weather } from './Weather';\n\ntype PropsType = {\n chatId?: string;\n message: ChatMessageType;\n isLoading: boolean;\n bot: BotType | null;\n enableTTS?: boolean;\n};\n\nconst PreviewMessage: FC<PropsType> = ({\n chatId,\n message,\n bot,\n enableTTS,\n isLoading,\n}) => {\n const { theme, overrideConfig } = useConfiguration();\n const { listeners } = useChatData();\n\n const usedTools = useMemo(() => {\n return categorizeTools(message.usedTools || [], !!message.new);\n }, [message.usedTools, message.new]);\n\n const role = useMemo(() => {\n return getRole(message.role);\n }, [message.role]);\n\n const assistantAvatar = getAvatarSource(role, theme, bot?.avatar);\n\n const focusToolOutput = useMemo(() => {\n return hasFocusToolOutput(message.usedTools || []);\n }, [message.usedTools]);\n\n const messageContent = useMemo(() => {\n if (!focusToolOutput) {\n return message.content;\n }\n\n return removeToolOutputFromContent(\n message.content,\n message.usedTools || []\n );\n }, [focusToolOutput, message.content, message.usedTools]);\n\n useEffect(() => {\n const cmdTool = usedTools?.cmdToolResult as any;\n if (!cmdTool || !listeners?.['CMD_CALLBACK']) {\n return;\n }\n\n const tool = cmdTool as ToolUsage;\n listeners['CMD_CALLBACK']({\n tool: tool.tool,\n output: tool.toolOutput,\n });\n }, [usedTools]);\n\n return (\n <motion.div\n className=\"w-full mx-auto max-w-3xl px-4 group/message\"\n initial={{ y: 5, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n data-role={role}\n >\n <div className=\"flex justify-end text-[14px]\">\n {message?.fileUploads && !!message.fileUploads.length && (\n <PreviewAttachment attachment={message.fileUploads[0]} />\n )}\n </div>\n <div\n className={cn(\n `group-data-[role=user]/message:bg-[#FFF] group-data-[role=user]/message:rounded-[24px] text-[#18181B] group-data-[role=user]/message:px-[16px] group-data-[role=user]/message:py-[10px] flex gap-4 w-full group-data-[role=user]/message:w-fit group-data-[role=user]/message:ml-auto group-data-[role=user]/message:max-w-2xl overflow-x-hidden break-all`\n )}\n style={{\n backgroundColor: getMessageBackgroundColor(role, theme),\n }}\n >\n {shouldShowAvatar(theme, message.role) && (\n <div className=\"size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border\">\n {assistantAvatar ? (\n <img\n src={assistantAvatar}\n alt={bot?.name ?? 'User Avatar'}\n width={24}\n height={24}\n className=\"rounded-full\"\n />\n ) : (\n <SparklesIcon size={14} />\n )}\n </div>\n )}\n\n <div className=\"flex flex-col gap-2 w-full\">\n {/* Agent Thinking Display */}\n {message?.agentSteps && !!message.agentSteps.length && (\n <AgentThinking steps={message.agentSteps} isLoading={isLoading} />\n )}\n\n {/* Message Content */}\n {!!messageContent && (\n <div\n className=\"flex flex-col gap-4\"\n style={{\n color: getMessageTextColor(role, theme),\n }}\n >\n <Markdown\n usedTools={focusToolOutput ? undefined : message?.usedTools}\n >\n {messageContent as string}\n </Markdown>\n </div>\n )}\n\n {/* Audio Player */}\n {!focusToolOutput && (role === 'assistant' || message?.ttsUrl) && (\n <AudioPlayer\n chatId={chatId}\n message={message}\n autoplay={!!enableTTS}\n />\n )}\n\n {/* Custom Tool Results */}\n {!!usedTools?.customToolResults?.length && (\n <div className=\"flex flex-col gap-4 custom-tools\">\n {usedTools.customToolResults.map((usedTool, index) => {\n const { tool, toolOutput, toolInput } = usedTool;\n const outputData = parseToolOutput(toolOutput);\n return (\n <div key={`${tool}-${index}`} className=\"custom-tool-result\">\n {!!outputData && isWeatherTool(tool) && (\n <Weather weatherAtLocation={outputData} />\n )}\n {!!outputData?.data?.getCMSLocationInfoDetail &&\n tool === LOCATION_TOOLS.GET_ASSIGNED_LOCATION_DETAIL && (\n <LocationCard\n location={outputData.data.getCMSLocationInfoDetail}\n />\n )}\n {!!outputData &&\n tool === LOCATION_TOOLS.SEARCH_TRAVELING_PLACES && (\n <div className=\"flex flex-row overflow-x-auto\">\n {outputData.map((place: any) => (\n <div\n key={place.id}\n className=\"flex-shrink-0 pr-2 max-w-full\"\n >\n <LocationCard location={place} />\n </div>\n ))}\n </div>\n )}\n {!!toolOutput && isDisplayProductListTool(tool) && (\n <ProductList\n productCodes={(outputData as any).product_codes}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayProductDetailTool(tool) && (\n <ProductDetail\n productCode={(outputData as any).product_code}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayScenariosTool(tool) && (\n <ScenariosList\n scenarioCodes={(outputData as any)?.scenario_codes}\n tourCode={overrideConfig?.vars?.TOUR_CODE}\n languageCode={overrideConfig?.vars?.LANGUAGE_CODE}\n apiUrl={overrideConfig?.vars?.CLIK_GRAPHQL_API}\n />\n )}\n {!!toolOutput && isDisplayBookingFormTool(tool) && (\n <BookMeetingForm />\n )}\n {!!toolOutput && isDisplayContactFormTool(tool) && (\n <UserContactForm />\n )}\n {!!toolOutput && isHtmlContent(usedTool) && (\n <HtmlContent content={outputData.content} />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </motion.div>\n );\n};\n\nexport const ThinkingMessage = ({ bot }: { bot: BotType | null }) => {\n const role = 'assistant';\n\n const { theme } = useConfiguration();\n\n const assistantAvatar = getAvatarSource(role, theme, bot?.avatar);\n\n return (\n <motion.div\n className=\"w-full mx-auto max-w-3xl px-4 group/message\"\n initial={{ y: 5, opacity: 0 }}\n animate={{ y: 0, opacity: 1, transition: { delay: 1 } }}\n data-role={role}\n >\n <div\n className={cn(\n 'flex gap-4 group-data-[role=user]/message:px-3 w-full group-data-[role=user]/message:w-fit group-data-[role=user]/message:ml-auto group-data-[role=user]/message:max-w-2xl group-data-[role=user]/message:py-2 rounded-xl',\n {\n 'group-data-[role=user]/message:bg-muted': true,\n }\n )}\n >\n {shouldShowAvatar(theme, 'apiMessage') && (\n <div className=\"size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border\">\n <img\n src={assistantAvatar}\n alt={bot?.name ?? 'User Avatar'}\n width={24}\n height={24}\n className=\"rounded-full\"\n />\n </div>\n )}\n <div className=\"flex flex-col gap-2 w-full\">\n <div className=\"flex flex-col gap-4 text-muted-foreground\">\n Thinking...\n </div>\n </div>\n </div>\n </motion.div>\n );\n};\n\nexport default React.memo(PreviewMessage);"]}
@@ -1,7 +1,5 @@
1
1
  import React from 'react';
2
- import { ProductType } from 'types/product.type';
3
2
  interface PropTypes {
4
- content?: ProductType | string;
5
3
  productCode?: string;
6
4
  tourCode?: string;
7
5
  languageCode?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProductDetail.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/ProductDetail.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAWxE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;AAuVD,wBAAyC"}
1
+ {"version":3,"file":"ProductDetail.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/ProductDetail.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,UAAU,SAAS;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;AA8QD,wBAAyC"}
@@ -1,43 +1,24 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Marked, Renderer } from '@ts-stack/markdown';
3
- import React, { useEffect, useRef, useState, useMemo } from 'react';
2
+ import React, { useEffect, useState, useMemo } from 'react';
4
3
  import { useChatData } from '../../hooks/useChatData';
5
4
  import { getProductDetails } from '../../services/vt360.service';
6
5
  import { BookmarkIcon, Product360Icon, ProductARIcon, ProductGalleryIcon, ProductInfoIcon, } from './Icons';
7
6
  import { convertCurrencyVnd, formatPriceProduct } from 'utils/currency';
8
- const ProductDetail = ({ content, productCode, tourCode, languageCode = 'VN', apiUrl, }) => {
9
- const botMessageElRef = useRef(null);
10
- const [stringData, setStringData] = useState('');
7
+ const ProductDetail = ({ productCode, tourCode, languageCode = 'VN', apiUrl, }) => {
11
8
  const [data, setData] = useState(null);
12
9
  const [loading, setLoading] = useState(false);
13
- const [error, setError] = useState(null);
14
10
  const { listeners } = useChatData();
15
- useEffect(() => {
16
- if (!content) {
17
- return;
18
- }
19
- if (typeof content === 'string' || content instanceof String) {
20
- setStringData(content);
21
- }
22
- else {
23
- if (content?.code) {
24
- setData(content);
25
- }
26
- }
27
- }, [content]);
28
11
  useEffect(() => {
29
12
  const fetchProductData = async () => {
30
13
  if (!productCode || !tourCode) {
31
14
  return;
32
15
  }
33
16
  setLoading(true);
34
- setError(null);
35
17
  try {
36
18
  const productData = await getProductDetails(productCode, tourCode, languageCode, apiUrl ? { api: apiUrl } : undefined);
37
19
  setData(productData);
38
20
  }
39
21
  catch (err) {
40
- setError(err instanceof Error ? err.message : 'Failed to fetch product details');
41
22
  console.error('Error fetching product details:', err);
42
23
  }
43
24
  finally {
@@ -45,37 +26,7 @@ const ProductDetail = ({ content, productCode, tourCode, languageCode = 'VN', ap
45
26
  }
46
27
  };
47
28
  fetchProductData();
48
- }, [productCode, tourCode, languageCode, apiUrl]);
49
- useEffect(() => {
50
- const botMessageEl = botMessageElRef.current;
51
- if (!stringData || !botMessageEl) {
52
- return;
53
- }
54
- Marked.setOptions({
55
- renderer: new Renderer(),
56
- gfm: true,
57
- tables: true,
58
- breaks: false,
59
- pedantic: false,
60
- sanitize: false,
61
- smartLists: true,
62
- smartypants: false,
63
- });
64
- botMessageEl.innerHTML = Marked.parse(stringData);
65
- botMessageEl.querySelectorAll('a').forEach((link) => {
66
- if (listeners?.['ON_LINK_CLICK']) {
67
- link['data-json'] = link.href;
68
- link.href = 'javascript:void(0);';
69
- link.target = '';
70
- link.onclick = () => {
71
- listeners['ON_LINK_CLICK'](link['data-json']);
72
- };
73
- }
74
- else {
75
- link.target = '_blank';
76
- }
77
- });
78
- }, [stringData]);
29
+ }, [productCode]);
79
30
  const handleOnClick = (url) => {
80
31
  if (listeners?.['ON_LINK_CLICK']) {
81
32
  listeners['ON_LINK_CLICK'](url);
@@ -155,8 +106,6 @@ const ProductDetail = ({ content, productCode, tourCode, languageCode = 'VN', ap
155
106
  }
156
107
  };
157
108
  const loadingComponent = useMemo(() => (_jsx("div", { className: "py-4", children: _jsx("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: _jsxs("div", { className: "animate-pulse", children: [_jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4 mb-4" }), _jsx("div", { className: "h-48 bg-gray-200 rounded mb-4" }), _jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2" })] }) }) })), []);
158
- const errorComponent = useMemo(() => (_jsx("div", { className: "py-4", children: _jsx("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 text-red-700", children: error }) })), [error]);
159
- const stringDataComponent = useMemo(() => (_jsx("span", { className: "product-detail bg-white text-gray-700 text-base rounded-md", ref: botMessageElRef })), [stringData]);
160
109
  const cardAction = [
161
110
  {
162
111
  label: 'Info',
@@ -192,6 +141,8 @@ const ProductDetail = ({ content, productCode, tourCode, languageCode = 'VN', ap
192
141
  return null;
193
142
  return (_jsx("div", { className: "py-4", children: _jsxs("div", { className: "bg-white rounded-lg overflow-hidden w-full p-[12px] gap-[12px] flex flex-col justify-center items-start", children: [_jsxs("div", { className: "flex flex-col w-full gap-1", children: [_jsx("div", { className: "flex flex-row items-center w-full h-6 gap-1", children: _jsx("h2", { className: "text-card-foreground truncate font-semibold text-[16px] leading-6 flex-1 min-w-0", children: data.name }) }), _jsxs("div", { className: "flex w-full gap-[4px] justify-between", children: [_jsxs("div", { className: "min-w-0", children: [data.tourProductQuotations.length > 0 && (_jsx("span", { className: "text-card-foreground text-[16px] leading-[24px] font-semibold", children: `${formatPriceProduct(convertCurrencyVnd(data.tourProductQuotations[0]?.price.toString() ?? ''), data.currencyUnit ?? '', data.unit ?? '')} ` })), _jsx("span", { className: `${data.tourProductQuotations.length > 0 ? 'line-through text-muted-foreground text-[14px] leading-[14px] font-medium' : 'text-card-foreground text-[16px] leading-[24px] font-semibold'}`, children: `${formatPriceProduct(convertCurrencyVnd(data?.price.toString() ?? ''), data.currencyUnit ?? '', data.unit ?? '')} ` })] }), _jsx("div", { className: "flex justify-center items-center w-5 h-5", children: _jsx(BookmarkIcon, { size: 20, color: "#71717A" }) })] }), _jsx("p", { className: "text-muted-foreground w-full font-normal text-[14px] leading-5 overflow-hidden line-clamp-2", children: data.description })] }), _jsx("div", { className: "flex flex-row items-center w-full relative gap-3 pb-[56%]", children: _jsx("div", { className: "absolute top-0 left-0 cursor-pointer w-full h-full bg-cover bg-center rounded-[5px] flex-1", style: {
194
143
  backgroundImage: `url(${data.icon?.url || data.logo?.url})`,
144
+ backgroundSize: 'contain',
145
+ backgroundRepeat: 'no-repeat',
195
146
  }, onClick: () => handleOnClick(data.virtualTourUrl) }) }), _jsx("div", { className: "flex flex-row items-center w-full h-6 gap-3", children: _jsx("div", { className: "flex flex-row items-center h-6 gap-3", children: cardAction.map((item) => {
196
147
  if (!item.isShow) {
197
148
  return null;
@@ -199,7 +150,7 @@ const ProductDetail = ({ content, productCode, tourCode, languageCode = 'VN', ap
199
150
  return (_jsxs("button", { className: "flex flex-row items-center hover:opacity-80 transition-opacity w-fit h-6 px-[8px] py-[2px] gap-[4px] bg-secondary border rounded-[8px]", onClick: () => handleActionClick(item.key), children: [_jsx("div", { className: "flex justify-center items-center w-5 h-5", children: item.icon }), _jsx("span", { className: "font-medium text-[14px] leading-5 text-muted-foreground", children: item.label })] }, item.key));
200
151
  }) }) })] }) }));
201
152
  }, [data, handleOnClick, handleActionClick]);
202
- return (_jsxs(_Fragment, { children: [loading && loadingComponent, error && errorComponent, !!stringData && stringDataComponent, !!data && productDataComponent] }));
153
+ return (_jsxs(_Fragment, { children: [loading && loadingComponent, !!data && productDataComponent] }));
203
154
  };
204
155
  export default React.memo(ProductDetail);
205
156
  //# sourceMappingURL=ProductDetail.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductDetail.js","sourceRoot":"","sources":["../../../src/components/Chat/ProductDetail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Marked, Renderer } from '@ts-stack/markdown';\nimport React, { FC, useEffect, useRef, useState, useMemo } from 'react';\nimport { useChatData } from '../../hooks/useChatData';\nimport { getProductDetails } from '../../services/vt360.service';\nimport {\n BookmarkIcon,\n Product360Icon,\n ProductARIcon,\n ProductGalleryIcon,\n ProductInfoIcon,\n} from './Icons';\nimport { convertCurrencyVnd, formatPriceProduct } from 'utils/currency';\nimport { ProductType } from 'types/product.type';\n\ninterface PropTypes {\n content?: ProductType | string;\n productCode?: string;\n tourCode?: string;\n languageCode?: string;\n apiUrl?: string;\n}\n\nconst ProductDetail: FC<PropTypes> = ({\n content,\n productCode,\n tourCode,\n languageCode = 'VN',\n apiUrl,\n}) => {\n const botMessageElRef = useRef<HTMLSpanElement | null>(null);\n const [stringData, setStringData] = useState<string>('');\n const [data, setData] = useState<ProductType | null>(null);\n const [loading, setLoading] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const { listeners } = useChatData();\n\n useEffect(() => {\n if (!content) {\n return;\n }\n if (typeof content === 'string' || content instanceof String) {\n setStringData(content as string);\n } else {\n if (content?.code) {\n setData(content as ProductType);\n }\n }\n }, [content]);\n\n useEffect(() => {\n const fetchProductData = async () => {\n if (!productCode || !tourCode) {\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const productData = await getProductDetails(\n productCode,\n tourCode,\n languageCode,\n apiUrl ? { api: apiUrl } : undefined\n );\n setData(productData);\n } catch (err) {\n setError(\n err instanceof Error ? err.message : 'Failed to fetch product details'\n );\n console.error('Error fetching product details:', err);\n } finally {\n setLoading(false);\n }\n };\n\n fetchProductData();\n }, [productCode, tourCode, languageCode, apiUrl]);\n useEffect(() => {\n const botMessageEl = botMessageElRef.current;\n if (!stringData || !botMessageEl) {\n return;\n }\n\n Marked.setOptions({\n renderer: new Renderer(),\n gfm: true,\n tables: true,\n breaks: false,\n pedantic: false,\n sanitize: false,\n smartLists: true,\n smartypants: false,\n });\n botMessageEl.innerHTML = Marked.parse(stringData);\n\n botMessageEl.querySelectorAll('a').forEach((link) => {\n if (listeners?.['ON_LINK_CLICK']) {\n (link as any)['data-json'] = link.href;\n link.href = 'javascript:void(0);';\n link.target = '';\n link.onclick = () => {\n listeners['ON_LINK_CLICK']((link as any)['data-json']);\n };\n } else {\n link.target = '_blank';\n }\n });\n }, [stringData]);\n\n const handleOnClick = (url: string) => {\n if (listeners?.['ON_LINK_CLICK']) {\n listeners['ON_LINK_CLICK'](url);\n } else {\n window?.open(url, '_blank');\n }\n };\n\n const handleActionClick = (action: string) => {\n if (!listeners?.['CMD_CALLBACK']) {\n return;\n }\n // template command tool {\"tool\":\"show_product_image_gallery\",\"toolInput\":{\"product_code\":\"ITEM27GETN2D2M94\"},\"toolOutput\":\"[{\\\"type\\\":\\\"text\\\",\\\"text\\\":\\\"{\\\\n \\\\\\\"action\\\\\\\": \\\\\\\"show_product_image_gallery\\\\\\\",\\\\n \\\\\\\"product_code\\\\\\\": \\\\\\\"ITEM27GETN2D2M94\\\\\\\",\\\\n \\\\\\\"status\\\\\\\": \\\\\\\"opening\\\\\\\",\\\\n \\\\\\\"message\\\\\\\": \\\\\\\"Opening image gallery for product ITEM27GETN2D2M94\\\\\\\"\\\\n}\\\"}]\"}\n let cmdTool = null;\n switch (action) {\n case 'PRODUCT_INFO':\n cmdTool = {\n tool: 'show_product_info',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_info',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_GALLERY':\n cmdTool = {\n tool: 'show_product_image_gallery',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_image_gallery',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_360':\n cmdTool = {\n tool: 'show_product_360_image',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_360_image',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_AR':\n cmdTool = {\n tool: 'show_product_AR',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_AR',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n default:\n break;\n }\n if (cmdTool) {\n listeners['CMD_CALLBACK'](cmdTool);\n }\n };\n\n const loadingComponent = useMemo(\n () => (\n <div className=\"py-4\">\n <div className=\"bg-white rounded-lg border border-gray-200 p-4\">\n <div className=\"animate-pulse\">\n <div className=\"h-4 bg-gray-200 rounded w-3/4 mb-4\"></div>\n <div className=\"h-48 bg-gray-200 rounded mb-4\"></div>\n <div className=\"h-4 bg-gray-200 rounded w-1/2\"></div>\n </div>\n </div>\n </div>\n ),\n []\n );\n\n const errorComponent = useMemo(\n () => (\n <div className=\"py-4\">\n <div className=\"bg-red-50 border border-red-200 rounded-lg p-4 text-red-700\">\n {error}\n </div>\n </div>\n ),\n [error]\n );\n\n const stringDataComponent = useMemo(\n () => (\n <span\n className=\"product-detail bg-white text-gray-700 text-base rounded-md\"\n ref={botMessageElRef}\n />\n ),\n [stringData]\n );\n\n const cardAction = [\n {\n label: 'Info',\n key: 'PRODUCT_INFO',\n icon: <ProductInfoIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_INFO'),\n isShow: true,\n },\n {\n label: 'Gallery',\n key: 'PRODUCT_GALLERY',\n icon: <ProductGalleryIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_GALLERY'),\n isShow: data?.collections?.some(\n (item) => item.gallery?.length && item.gallery?.length > 0\n ),\n },\n {\n label: '360',\n key: 'PRODUCT_360',\n icon: <Product360Icon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_360'),\n isShow: data?.collections.some((item) => item.webRotateCode),\n },\n {\n label: 'AR',\n key: 'PRODUCT_AR',\n icon: <ProductARIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_AR'),\n isShow: data?.collections.some(\n (item) => item.model3DAndroid?.url || item.model3DIos?.url\n ),\n },\n ];\n\n const productDataComponent = useMemo(() => {\n if (!data) return null;\n\n return (\n <div className=\"py-4\">\n {/* item-card: full width responsive with 12px padding and 12px gap */}\n <div className=\"bg-white rounded-lg overflow-hidden w-full p-[12px] gap-[12px] flex flex-col justify-center items-start\">\n {/* content: full width x 68px with 4px gap */}\n <div className=\"flex flex-col w-full gap-1\">\n {/* price section: 334px x 24px with 4px gap */}\n <div className=\"flex flex-row items-center w-full h-6 gap-1\">\n {/* ARC Dining Table - now takes flex-grow: 1 */}\n <h2 className=\"text-card-foreground truncate font-semibold text-[16px] leading-6 flex-1 min-w-0\">\n {data.name}\n </h2>\n\n {/* Bookmark icon: 20px x 20px */}\n </div>\n <div className=\"flex w-full gap-[4px] justify-between\">\n <div className=\"min-w-0\">\n {data.tourProductQuotations.length > 0 && (\n <span className=\"text-card-foreground text-[16px] leading-[24px] font-semibold\">\n {`${formatPriceProduct(\n convertCurrencyVnd(\n data.tourProductQuotations[0]?.price.toString() ?? ''\n ),\n data.currencyUnit ?? '',\n data.unit ?? ''\n )} `}\n </span>\n )}\n <span\n className={`${data.tourProductQuotations.length > 0 ? 'line-through text-muted-foreground text-[14px] leading-[14px] font-medium' : 'text-card-foreground text-[16px] leading-[24px] font-semibold'}`}\n >\n {`${formatPriceProduct(\n convertCurrencyVnd(data?.price.toString() ?? ''),\n data.currencyUnit ?? '',\n data.unit ?? ''\n )} `}\n </span>\n </div>\n <div className=\"flex justify-center items-center w-5 h-5\">\n <BookmarkIcon size={20} color=\"#71717A\" />\n </div>\n </div>\n {/* Description text */}\n <p className=\"text-muted-foreground w-full font-normal text-[14px] leading-5 overflow-hidden line-clamp-2\">\n {data.description}\n </p>\n </div>\n {/* gallery: full width x 187.88px with 12px gap */}\n <div className=\"flex flex-row items-center w-full relative gap-3 pb-[56%]\">\n {/* Main Image */}\n <div\n className=\"absolute top-0 left-0 cursor-pointer w-full h-full bg-cover bg-center rounded-[5px] flex-1\"\n style={{\n backgroundImage: `url(${data.icon?.url || data.logo?.url})`,\n }}\n onClick={() => handleOnClick(data.virtualTourUrl)}\n />\n </div>\n\n {/* right: full width x 24px with 12px gap */}\n <div className=\"flex flex-row items-center w-full h-6 gap-3\">\n {/* content: 316px x 24px with 12px gap - contains the 4 buttons */}\n <div className=\"flex flex-row items-center h-6 gap-3\">\n {/* Info button: 66px x 24px */}\n {cardAction.map((item) => {\n if (!item.isShow) {\n return null;\n }\n return (\n <button\n key={item.key}\n className=\"flex flex-row items-center hover:opacity-80 transition-opacity w-fit h-6 px-[8px] py-[2px] gap-[4px] bg-secondary border rounded-[8px]\"\n onClick={() => handleActionClick(item.key)}\n >\n <div className=\"flex justify-center items-center w-5 h-5\">\n {item.icon}\n </div>\n <span className=\"font-medium text-[14px] leading-5 text-muted-foreground\">\n {item.label}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </div>\n </div>\n );\n }, [data, handleOnClick, handleActionClick]);\n\n return (\n <>\n {loading && loadingComponent}\n {error && errorComponent}\n {!!stringData && stringDataComponent}\n {!!data && productDataComponent}\n </>\n );\n};\n\nexport default React.memo(ProductDetail);\n"]}
1
+ {"version":3,"file":"ProductDetail.js","sourceRoot":"","sources":["../../../src/components/Chat/ProductDetail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Marked, Renderer } from '@ts-stack/markdown';\nimport React, { FC, useEffect, useRef, useState, useMemo } from 'react';\nimport { useChatData } from '../../hooks/useChatData';\nimport { getProductDetails } from '../../services/vt360.service';\nimport {\n BookmarkIcon,\n Product360Icon,\n ProductARIcon,\n ProductGalleryIcon,\n ProductInfoIcon,\n} from './Icons';\nimport { convertCurrencyVnd, formatPriceProduct } from 'utils/currency';\nimport { ProductType } from 'types/product.type';\n\ninterface PropTypes {\n productCode?: string;\n tourCode?: string;\n languageCode?: string;\n apiUrl?: string;\n}\n\nconst ProductDetail: FC<PropTypes> = ({\n productCode,\n tourCode,\n languageCode = 'VN',\n apiUrl,\n}) => {\n const [data, setData] = useState<ProductType | null>(null);\n const [loading, setLoading] = useState<boolean>(false);\n const { listeners } = useChatData();\n\n useEffect(() => {\n const fetchProductData = async () => {\n if (!productCode || !tourCode) {\n return;\n }\n\n setLoading(true);\n\n try {\n const productData = await getProductDetails(\n productCode,\n tourCode,\n languageCode,\n apiUrl ? { api: apiUrl } : undefined\n );\n setData(productData);\n } catch (err) {\n console.error('Error fetching product details:', err);\n } finally {\n setLoading(false);\n }\n };\n\n fetchProductData();\n }, [productCode]);\n\n const handleOnClick = (url: string) => {\n if (listeners?.['ON_LINK_CLICK']) {\n listeners['ON_LINK_CLICK'](url);\n } else {\n window?.open(url, '_blank');\n }\n };\n\n const handleActionClick = (action: string) => {\n if (!listeners?.['CMD_CALLBACK']) {\n return;\n }\n // template command tool {\"tool\":\"show_product_image_gallery\",\"toolInput\":{\"product_code\":\"ITEM27GETN2D2M94\"},\"toolOutput\":\"[{\\\"type\\\":\\\"text\\\",\\\"text\\\":\\\"{\\\\n \\\\\\\"action\\\\\\\": \\\\\\\"show_product_image_gallery\\\\\\\",\\\\n \\\\\\\"product_code\\\\\\\": \\\\\\\"ITEM27GETN2D2M94\\\\\\\",\\\\n \\\\\\\"status\\\\\\\": \\\\\\\"opening\\\\\\\",\\\\n \\\\\\\"message\\\\\\\": \\\\\\\"Opening image gallery for product ITEM27GETN2D2M94\\\\\\\"\\\\n}\\\"}]\"}\n let cmdTool = null;\n switch (action) {\n case 'PRODUCT_INFO':\n cmdTool = {\n tool: 'show_product_info',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_info',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_GALLERY':\n cmdTool = {\n tool: 'show_product_image_gallery',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_image_gallery',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_360':\n cmdTool = {\n tool: 'show_product_360_image',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_360_image',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n case 'PRODUCT_AR':\n cmdTool = {\n tool: 'show_product_AR',\n output: JSON.stringify([\n {\n type: 'text',\n text: JSON.stringify({\n action: 'show_product_AR',\n product_code: data?.code,\n }),\n },\n ]),\n };\n break;\n default:\n break;\n }\n if (cmdTool) {\n listeners['CMD_CALLBACK'](cmdTool);\n }\n };\n\n const loadingComponent = useMemo(\n () => (\n <div className=\"py-4\">\n <div className=\"bg-white rounded-lg border border-gray-200 p-4\">\n <div className=\"animate-pulse\">\n <div className=\"h-4 bg-gray-200 rounded w-3/4 mb-4\"></div>\n <div className=\"h-48 bg-gray-200 rounded mb-4\"></div>\n <div className=\"h-4 bg-gray-200 rounded w-1/2\"></div>\n </div>\n </div>\n </div>\n ),\n []\n );\n\n const cardAction = [\n {\n label: 'Info',\n key: 'PRODUCT_INFO',\n icon: <ProductInfoIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_INFO'),\n isShow: true,\n },\n {\n label: 'Gallery',\n key: 'PRODUCT_GALLERY',\n icon: <ProductGalleryIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_GALLERY'),\n isShow: data?.collections?.some(\n (item) => item.gallery?.length && item.gallery?.length > 0\n ),\n },\n {\n label: '360',\n key: 'PRODUCT_360',\n icon: <Product360Icon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_360'),\n isShow: data?.collections.some((item) => item.webRotateCode),\n },\n {\n label: 'AR',\n key: 'PRODUCT_AR',\n icon: <ProductARIcon size={20} color=\"#71717A\" />,\n onClick: () => handleActionClick('PRODUCT_AR'),\n isShow: data?.collections.some(\n (item) => item.model3DAndroid?.url || item.model3DIos?.url\n ),\n },\n ];\n\n const productDataComponent = useMemo(() => {\n if (!data) return null;\n\n return (\n <div className=\"py-4\">\n {/* item-card: full width responsive with 12px padding and 12px gap */}\n <div className=\"bg-white rounded-lg overflow-hidden w-full p-[12px] gap-[12px] flex flex-col justify-center items-start\">\n {/* content: full width x 68px with 4px gap */}\n <div className=\"flex flex-col w-full gap-1\">\n {/* price section: 334px x 24px with 4px gap */}\n <div className=\"flex flex-row items-center w-full h-6 gap-1\">\n {/* ARC Dining Table - now takes flex-grow: 1 */}\n <h2 className=\"text-card-foreground truncate font-semibold text-[16px] leading-6 flex-1 min-w-0\">\n {data.name}\n </h2>\n\n {/* Bookmark icon: 20px x 20px */}\n </div>\n <div className=\"flex w-full gap-[4px] justify-between\">\n <div className=\"min-w-0\">\n {data.tourProductQuotations.length > 0 && (\n <span className=\"text-card-foreground text-[16px] leading-[24px] font-semibold\">\n {`${formatPriceProduct(\n convertCurrencyVnd(\n data.tourProductQuotations[0]?.price.toString() ?? ''\n ),\n data.currencyUnit ?? '',\n data.unit ?? ''\n )} `}\n </span>\n )}\n <span\n className={`${data.tourProductQuotations.length > 0 ? 'line-through text-muted-foreground text-[14px] leading-[14px] font-medium' : 'text-card-foreground text-[16px] leading-[24px] font-semibold'}`}\n >\n {`${formatPriceProduct(\n convertCurrencyVnd(data?.price.toString() ?? ''),\n data.currencyUnit ?? '',\n data.unit ?? ''\n )} `}\n </span>\n </div>\n <div className=\"flex justify-center items-center w-5 h-5\">\n <BookmarkIcon size={20} color=\"#71717A\" />\n </div>\n </div>\n {/* Description text */}\n <p className=\"text-muted-foreground w-full font-normal text-[14px] leading-5 overflow-hidden line-clamp-2\">\n {data.description}\n </p>\n </div>\n {/* gallery: full width x 187.88px with 12px gap */}\n <div className=\"flex flex-row items-center w-full relative gap-3 pb-[56%]\">\n {/* Main Image */}\n <div\n className=\"absolute top-0 left-0 cursor-pointer w-full h-full bg-cover bg-center rounded-[5px] flex-1\"\n style={{\n backgroundImage: `url(${data.icon?.url || data.logo?.url})`,\n backgroundSize: 'contain',\n backgroundRepeat: 'no-repeat',\n }}\n onClick={() => handleOnClick(data.virtualTourUrl)}\n />\n </div>\n\n {/* right: full width x 24px with 12px gap */}\n <div className=\"flex flex-row items-center w-full h-6 gap-3\">\n {/* content: 316px x 24px with 12px gap - contains the 4 buttons */}\n <div className=\"flex flex-row items-center h-6 gap-3\">\n {/* Info button: 66px x 24px */}\n {cardAction.map((item) => {\n if (!item.isShow) {\n return null;\n }\n return (\n <button\n key={item.key}\n className=\"flex flex-row items-center hover:opacity-80 transition-opacity w-fit h-6 px-[8px] py-[2px] gap-[4px] bg-secondary border rounded-[8px]\"\n onClick={() => handleActionClick(item.key)}\n >\n <div className=\"flex justify-center items-center w-5 h-5\">\n {item.icon}\n </div>\n <span className=\"font-medium text-[14px] leading-5 text-muted-foreground\">\n {item.label}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </div>\n </div>\n );\n }, [data, handleOnClick, handleActionClick]);\n\n return (\n <>\n {loading && loadingComponent}\n {!!data && productDataComponent}\n </>\n );\n};\n\nexport default React.memo(ProductDetail);\n"]}
@@ -1,12 +1,6 @@
1
1
  import React from 'react';
2
- import { ProductType } from 'types/product.type';
3
- interface ProductDataResultType {
4
- products: ProductType[];
5
- scenarioUrl: string;
6
- }
7
2
  interface PropTypes {
8
- content?: ProductDataResultType | string;
9
- productCodesStr?: string;
3
+ productCodes?: string[];
10
4
  tourCode?: string;
11
5
  languageCode?: string;
12
6
  apiUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProductList.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/ProductList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOjD,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;AAiWD,wBAAuC"}
1
+ {"version":3,"file":"ProductList.d.ts","sourceRoot":"","sources":["../../../src/components/Chat/ProductList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAiBxE,UAAU,SAAS;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;AA+QD,wBAAuC"}
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Marked, Renderer } from '@ts-stack/markdown';
3
- import React, { useEffect, useRef, useState, useMemo } from 'react';
2
+ import React, { useEffect, useState, useMemo } from 'react';
4
3
  import { useChatData } from '../../hooks/useChatData';
5
4
  import { getProducts } from '../../services/vt360.service';
6
5
  import { BookmarkIcon } from './Icons';
@@ -9,42 +8,21 @@ const FORMATTER = new Intl.NumberFormat('vi-VN', {
9
8
  style: 'currency',
10
9
  currency: 'VND',
11
10
  });
12
- const ProductList = ({ content, productCodesStr, tourCode, languageCode = 'VN', apiUrl, }) => {
13
- const botMessageElRef = useRef(null);
14
- const [stringData, setStringData] = useState('');
11
+ const ProductList = ({ productCodes, tourCode, languageCode = 'VN', apiUrl, }) => {
15
12
  const [data, setData] = useState(null);
16
13
  const [loading, setLoading] = useState(false);
17
- const [error, setError] = useState(null);
18
14
  const { listeners } = useChatData();
19
- const productCodes = useMemo(() => {
20
- if (!productCodesStr)
21
- return [];
22
- return productCodesStr.split(',').map((code) => code.trim());
23
- }, [productCodesStr]);
24
- useEffect(() => {
25
- if (!content) {
26
- return;
27
- }
28
- if (typeof content === 'string' || content instanceof String) {
29
- setStringData(content);
30
- }
31
- else {
32
- setData(content);
33
- }
34
- }, [content]);
35
15
  useEffect(() => {
36
16
  const fetchProductsData = async () => {
37
17
  if (!productCodes || !productCodes.length || !tourCode) {
38
18
  return;
39
19
  }
40
20
  setLoading(true);
41
- setError(null);
42
21
  try {
43
22
  const productsData = await getProducts(productCodes, tourCode, languageCode, apiUrl ? { api: apiUrl } : undefined);
44
23
  setData(productsData);
45
24
  }
46
25
  catch (err) {
47
- setError(err instanceof Error ? err.message : 'Failed to fetch products');
48
26
  console.error('Error fetching products:', err);
49
27
  }
50
28
  finally {
@@ -53,36 +31,6 @@ const ProductList = ({ content, productCodesStr, tourCode, languageCode = 'VN',
53
31
  };
54
32
  fetchProductsData();
55
33
  }, [productCodes, tourCode, languageCode, apiUrl]);
56
- useEffect(() => {
57
- const botMessageEl = botMessageElRef.current;
58
- if (!stringData || !botMessageEl) {
59
- return;
60
- }
61
- Marked.setOptions({
62
- renderer: new Renderer(),
63
- gfm: true,
64
- tables: true,
65
- breaks: false,
66
- pedantic: false,
67
- sanitize: false,
68
- smartLists: true,
69
- smartypants: false,
70
- });
71
- botMessageEl.innerHTML = Marked.parse(stringData);
72
- botMessageEl.querySelectorAll('a').forEach((link) => {
73
- if (listeners?.['ON_LINK_CLICK']) {
74
- link['data-json'] = link.href;
75
- link.href = 'javascript:void(0);';
76
- link.target = '';
77
- link.onclick = () => {
78
- listeners['ON_LINK_CLICK'](link['data-json']);
79
- };
80
- }
81
- else {
82
- link.target = '_blank';
83
- }
84
- });
85
- }, [stringData]);
86
34
  const handleOnClick = (url) => {
87
35
  if (listeners?.['ON_LINK_CLICK']) {
88
36
  listeners['ON_LINK_CLICK'](url);
@@ -162,13 +110,6 @@ const ProductList = ({ content, productCodesStr, tourCode, languageCode = 'VN',
162
110
  }
163
111
  };
164
112
  const loadingComponent = useMemo(() => (_jsx("div", { className: "py-4", children: _jsx("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: _jsxs("div", { className: "animate-pulse", children: [_jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4 mb-4" }), _jsx("div", { className: "h-20 bg-gray-200 rounded mb-4" }), _jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2" })] }) }) })), []);
165
- const errorComponent = useMemo(() => (_jsx("div", { className: "py-4", children: _jsx("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 text-red-700", children: error }) })), [error]);
166
- const stringDataComponent = useMemo(() => (_jsx("span", { className: "product-list", ref: botMessageElRef, style: {
167
- borderRadius: '6px',
168
- backgroundColor: 'rgb(255, 255, 255)',
169
- color: 'rgb(48, 50, 53)',
170
- fontSize: '16px',
171
- } })), [stringData]);
172
113
  const productListComponent = useMemo(() => {
173
114
  if (!data || (!data?.products?.length && !data?.scenarioUrl))
174
115
  return null;