import { Box, VStack, Button } from "@chakra-ui/react"; import { useState, useCallback, useEffect, useRef } from "react"; import { useChatContext, WidgetType } from "~/providers/chat/chat-context"; import { getSharingId } from "~/utils/sharing-id"; import { ProductCardData } from "~/types/product"; import { fetchBotDataWithProduct, trackPDPInteraction, trackDoriSession, API_URLS } from "~/utils/api"; import { getProductId, isProductPage } from "~/utils/product-context"; import SimpleInputField from "./SimpleInputField"; import { useBotInitializer } from "../widget/useBotInitializer"; import EmbeddedChatScreen from "../widget/screens/chat-screen/EmbeddedChatScreen"; import { FaCaretDown } from "react-icons/fa"; import { BsStars } from "react-icons/bs"; import MoriBranding from "../widget/components/MoriBranding"; import { COLORS } from "@/utils/constants"; import { captureApiError } from "~/utils/sentry"; import { updateBotData } from "~/utils/posthog"; export function EmbeddedWidget() { const { sendMessage, inputState, isInputDisabled, stopCurrentRequest, setWidgetType, chatState } = useChatContext(); const [showChat, setShowChat] = useState(false); const [suggestedPrompts, setSuggestedPrompts] = useState([]); const [selectedQuestion, setSelectedQuestion] = useState(null); const { botData: initialBotData } = useBotInitializer(WidgetType.EMBEDDED); const [faqsExpanded, setFaqsExpanded] = useState(false); const [answeredFaqs, setAnsweredFaqs] = useState>(new Set()); const isPdpEmbeddedWidgetEnabled = initialBotData?.is_pdp_embedded_widget_enabled ?? false; // Update PostHog bot data when available (fixes missing bot_id in events) useEffect(() => { if (initialBotData) { updateBotData(initialBotData); } }, [initialBotData]); useEffect(() => { setWidgetType(WidgetType.EMBEDDED); const sharingId = getSharingId(); if (!sharingId) return; if (!isPdpEmbeddedWidgetEnabled) return; const fetchBotData = async () => { try { const productId = getProductId(); const shouldUseProduct = isProductPage() && productId; if (shouldUseProduct && productId) { const result = await fetchBotDataWithProduct(sharingId, productId); if (result.data) { setSuggestedPrompts(result.data.suggested_prompts || []); } else { setSuggestedPrompts([]); } } } catch { setSuggestedPrompts([]); } }; fetchBotData(); }, [ isPdpEmbeddedWidgetEnabled, setWidgetType, initialBotData ]); const faqs: string[] = suggestedPrompts; const unansweredFaqs = faqs.filter((faq) => !answeredFaqs.has(faq)); const handleSendMessage = useCallback( async ( { message, imageUrl }: { message: string; imageUrl?: string; }, repliedProduct?: ProductCardData ) => { const trimmedMessage = message?.trim(); if (!trimmedMessage) return; setShowChat(true); setFaqsExpanded(true) await sendMessage({ message: trimmedMessage, imageUrl }, repliedProduct); }, [sendMessage] ); const handleSelectFAQ = useCallback( (q: string) => { setSelectedQuestion(q); setAnsweredFaqs((prev) => new Set(prev).add(q)); void handleSendMessage({ message: q }); }, [handleSendMessage] ); // Track PDP interaction when threadId is available useEffect(() => { if (chatState.threadId && selectedQuestion) { const productId = getProductId(); const sharingId = getSharingId(); if (productId && sharingId) { trackPDPInteraction( sharingId, chatState.threadId, productId, selectedQuestion, "wordpress" ).catch((error) => { console.error("Failed to track PDP interaction:", error); captureApiError( error, "trackPDPInteraction", API_URLS.trackPDPInteraction, "POST" ); }); // Clear the selected question after tracking setSelectedQuestion(null); } } }, [chatState.threadId, selectedQuestion]); // Track session when threadId is first initialized for embedded widget const lastTrackedThreadIdRef = useRef(null); useEffect(() => { if (chatState.threadId && initialBotData) { if (chatState.threadId !== lastTrackedThreadIdRef.current) { const sharingId = getSharingId(); if (sharingId) { trackDoriSession( sharingId, chatState.threadId, "wordpress", WidgetType.EMBEDDED ).catch((error) => { console.error("Failed to track session:", error); captureApiError( error, "trackDoriSession", API_URLS.trackSession, "POST" ); }); lastTrackedThreadIdRef.current = chatState.threadId; } } } }, [chatState.threadId, initialBotData]); if (initialBotData === null || faqs.length === 0) { return null; } return ( {showChat ? ( ) : ( {faqs.map((q, idx) => ( ))} {!faqsExpanded && faqs.length > 3 && ( )} )} ); }