diff --git a/backend/app/Resources/User/UserResource.php b/backend/app/Resources/User/UserResource.php index 5ee5a97677..bce47ed118 100644 --- a/backend/app/Resources/User/UserResource.php +++ b/backend/app/Resources/User/UserResource.php @@ -18,6 +18,7 @@ public function toArray(Request $request): array 'timezone' => $this->getTimezone(), 'first_name' => $this->getFirstName(), 'last_name' => $this->getLastName(), + 'full_name' => $this->getFullName(), 'email' => $this->getEmail(), 'is_email_verified' => $this->getEmailVerifiedAt() !== null, 'has_pending_email_change' => $this->getPendingEmail() !== null, diff --git a/frontend/src/components/common/ChatwootWidget/index.tsx b/frontend/src/components/common/ChatwootWidget/index.tsx new file mode 100644 index 0000000000..f04635d467 --- /dev/null +++ b/frontend/src/components/common/ChatwootWidget/index.tsx @@ -0,0 +1,105 @@ +import { useEffect, useRef } from "react"; +import { isSsr } from "../../../utilites/helpers.ts"; +import { useGetMe } from "../../../queries/useGetMe.ts"; +import { User } from "../../../types.ts"; +import { getConfig } from "../../../utilites/config.ts"; + +const CHATWOOT_ROUTES = ["/manage", "/account", "/welcome"]; + +const ChatwootWidget = () => { + const scriptRef = useRef(null); + const { data: me, isLoading } = useGetMe(); + const chatwootToken = getConfig('VITE_CHATWOOT_WEBSITE_TOKEN'); + const chatwootUrl = getConfig('VITE_CHATWOOT_BASE_URL') || 'https://app.chatwoot.com'; + + useEffect(() => { + if (isSsr() || isLoading || !chatwootToken) { + return; + } + + try { + const pathname = window.location.pathname; + if (!CHATWOOT_ROUTES.some(route => pathname.includes(route))) return; + + if (!document.getElementById("chatwoot-script")) { + const script = document.createElement("script"); + script.id = "chatwoot-script"; + script.src = `${chatwootUrl}/packs/js/sdk.js`; + script.defer = true; + script.async = true; + script.onload = () => { + window.chatwootSDK.run({ + websiteToken: chatwootToken, + baseUrl: chatwootUrl + }); + if (me) { + setChatwootUserDetails(me); + } + }; + document.body.appendChild(script); + scriptRef.current = script; + } else if (me) { + setChatwootUserDetails(me); + } + + const handleUrlChange = () => { + try { + const currentPath = window.location.pathname; + if (!CHATWOOT_ROUTES.some(route => currentPath.includes(route))) { + removeChatwootScript(); + } + } catch (error) { + console.error("Error in ChatwootWidget URL change handler:", error); + } + }; + + window.addEventListener("popstate", handleUrlChange); + + return () => { + window.removeEventListener("popstate", handleUrlChange); + removeChatwootScript(); + }; + } catch (error) { + console.error("Error initializing ChatwootWidget:", error); + } + }, [isLoading, me]); + + const removeChatwootScript = () => { + try { + const script = document.getElementById("chatwoot-script"); + if (script) { + script.remove(); + scriptRef.current = null; + } + } catch (error) { + console.error("Error removing ChatwootWidget script:", error); + } + }; + + const setChatwootUserDetails = (user: User) => { + try { + window.addEventListener("chatwoot:ready", () => { + if (!window.$chatwoot) return; + + window.$chatwoot.setUser(String(user.id), { + email: user.email, + name: user.full_name, + locale: user.locale || "en", + }); + + window.$chatwoot.setCustomAttributes({ + locale: user.locale || "en", + account_id: user.account_id || "Unknown", + user_role: user.role || "Unknown", + is_user_verified: user.is_email_verified, + }); + }); + } catch (error) { + console.error("Error setting Chatwoot user details:", error); + } + }; + + return null; +}; + +export default ChatwootWidget; diff --git a/frontend/src/components/common/ThirdPartyScripts/index.tsx b/frontend/src/components/common/ThirdPartyScripts/index.tsx index 3fdbad56a7..7786d4e01e 100644 --- a/frontend/src/components/common/ThirdPartyScripts/index.tsx +++ b/frontend/src/components/common/ThirdPartyScripts/index.tsx @@ -1,9 +1,9 @@ -import ZohoChatWidget from "../ZohoChatWidget"; +import ChatwootWidget from "../ChatwootWidget"; export const ThirdPartyScripts = () => { return ( <> - + ); } diff --git a/frontend/src/components/common/ZohoChatWidget/index.tsx b/frontend/src/components/common/ZohoChatWidget/index.tsx deleted file mode 100644 index 8d6b8f5fff..0000000000 --- a/frontend/src/components/common/ZohoChatWidget/index.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import {useEffect, useRef} from "react"; -import {isSsr} from "../../../utilites/helpers.ts"; - -const ZOHO_ROUTES = ["/manage", "/account", "/welcome"]; - -const ZohoChatWidget = () => { - const scriptRef = useRef(null); - - useEffect(() => { - if (isSsr()) return; - - try { - const pathname = window.location.pathname; - const widgetCode = window.hievents?.VITE_ZOHO_WIDGET_CODE; - - if (!widgetCode || !ZOHO_ROUTES.some(route => pathname.includes(route))) return; - - window.$zoho = window.$zoho || {}; - window.$zoho.salesiq = window.$zoho.salesiq || { - ready: () => { - } - }; - - if (!document.getElementById("zsiqscript")) { - const script = document.createElement("script"); - script.id = "zsiqscript"; - script.src = `https://salesiq.zohopublic.eu/widget?wc=${widgetCode}`; - script.defer = true; - document.body.appendChild(script); - scriptRef.current = script; - } - - const handleUrlChange = () => { - try { - const currentPath = window.location.pathname; - if (!ZOHO_ROUTES.some(route => currentPath.includes(route))) { - removeZohoScript(); - } - } catch (error) { - console.error("Error in ZohoChatWidget URL change handler:", error); - } - }; - - window.addEventListener("popstate", handleUrlChange); - - return () => { - window.removeEventListener("popstate", handleUrlChange); - removeZohoScript(); - }; - } catch (error) { - console.error("Error initializing ZohoChatWidget:", error); - } - }, []); - - const removeZohoScript = () => { - try { - const script = document.getElementById("zsiqscript"); - if (script) { - script.remove(); - scriptRef.current = null; - } - } catch (error) { - console.error("Error removing ZohoChatWidget script:", error); - } - }; - - return null; -}; - -export default ZohoChatWidget; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index f6633234ad..b8372e983a 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -7,6 +7,8 @@ export type ConfigKeys = 'VITE_FRONTEND_URL' | 'VITE_API_URL_CLIENT' | 'VITE_STRIPE_PUBLISHABLE_KEY' | 'VITE_API_URL_SERVER' + | 'VITE_CHATWOOT_WEBSITE_TOKEN' + | 'VITE_CHATWOOT_BASE_URL' | string; export type IdParam = string | undefined | number; @@ -41,6 +43,7 @@ export interface User { account_id?: IdParam; first_name: string; last_name: string; + full_name: string; email: string; timezone?: string; password?: string;