diff --git a/apps/web/modules/event-types/views/event-types-listing-view.tsx b/apps/web/modules/event-types/views/event-types-listing-view.tsx index fb61243ec0..2b1328c923 100644 --- a/apps/web/modules/event-types/views/event-types-listing-view.tsx +++ b/apps/web/modules/event-types/views/event-types-listing-view.tsx @@ -9,7 +9,6 @@ import { memo, useEffect, useState } from "react"; import { z } from "zod"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; -import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom"; import { EventTypeEmbedButton, EventTypeEmbedDialog } from "@calcom/features/embed/EventTypeEmbed"; import { EventTypeDescription } from "@calcom/features/eventtypes/components"; import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog"; @@ -950,8 +949,6 @@ const EventTypesPage: React.FC & { getLayout?: AppProps["Component"]["getLayout"]; } = () => { const { t } = useLocale(); - const searchParams = useCompatSearchParams(); - const { open } = useIntercom(); const { data: user } = useMeQuery(); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [showProfileBanner, setShowProfileBanner] = useState(false); @@ -966,13 +963,6 @@ const EventTypesPage: React.FC & { staleTime: 1 * 60 * 60 * 1000, }); - useEffect(() => { - if (searchParams?.get("openIntercom") === "true") { - open(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - useEffect(() => { setShowProfileBanner( !!orgBranding && !document.cookie.includes("calcom-profile-banner=1") && !user?.completedOnboarding diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index dbae30bf85..2a3018379e 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -2403,5 +2403,7 @@ "unreviewed": "Unreviewed", "rating_url_info":"The URL for Rating Feedback Form", "no_show_url_info":"The URL for No Show Feedback", + "no_support_needed":"No Support Needed?", + "hide_support":"Hide Support", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } \ No newline at end of file diff --git a/packages/features/ee/support/components/ContactMenuItem.tsx b/packages/features/ee/support/components/ContactMenuItem.tsx index 005433a25f..29553d2971 100644 --- a/packages/features/ee/support/components/ContactMenuItem.tsx +++ b/packages/features/ee/support/components/ContactMenuItem.tsx @@ -5,7 +5,6 @@ import { Icon, UpgradeTeamsBadge } from "@calcom/ui"; import FreshChatMenuItem from "../lib/freshchat/FreshChatMenuItem"; import HelpscoutMenuItem from "../lib/helpscout/HelpscoutMenuItem"; -import IntercomMenuItem from "../lib/intercom/IntercomMenuItem"; import ZendeskMenuItem from "../lib/zendesk/ZendeskMenuItem"; interface ContactMenuItem { @@ -20,7 +19,6 @@ export default function ContactMenuItem(props: ContactMenuItem) { <> {hasPaidPlan ? ( <> - diff --git a/packages/features/ee/support/components/HelpMenuItem.tsx b/packages/features/ee/support/components/HelpMenuItem.tsx index ed99d84542..64f46ff34b 100644 --- a/packages/features/ee/support/components/HelpMenuItem.tsx +++ b/packages/features/ee/support/components/HelpMenuItem.tsx @@ -2,9 +2,8 @@ import { useState } from "react"; import { useChat } from "react-live-chat-loader"; import classNames from "@calcom/lib/classNames"; -import { JOIN_DISCORD } from "@calcom/lib/constants"; -import { useHasPaidPlan } from "@calcom/lib/hooks/useHasPaidPlan"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { localStorage } from "@calcom/lib/webstorage"; import { trpc } from "@calcom/trpc/react"; import { Button, showToast, TextArea } from "@calcom/ui"; import { Icon } from "@calcom/ui"; @@ -20,13 +19,21 @@ interface HelpMenuItemProps { export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) { const [rating, setRating] = useState(null); - const { open } = useIntercom(); + const [showIntercom, setShowIntercom] = useState( + localStorage.getItem("showIntercom") === "false" ? false : true + ); + const { open, shutdown } = useIntercom(); const [comment, setComment] = useState(""); const [disableSubmit, setDisableSubmit] = useState(true); const [active, setActive] = useState(false); const [, loadChat] = useChat(); const { t } = useLocale(); + const toggleIntercom = (value: boolean) => { + setShowIntercom(value); + localStorage.setItem("showIntercom", String(value)); + }; + const { setActive: setFreshChat } = useFreshChat(); const mutation = trpc.viewer.submitFeedback.useMutation({ @@ -46,8 +53,6 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) { mutation.mutate({ rating: rating, comment: comment }); }; - const { hasPaidPlan } = useHasPaidPlan(); - return (
@@ -71,7 +76,6 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
-

{t("feedback").toUpperCase()}

@@ -188,13 +192,21 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
)} -
-

{t("specific_issue")}

- {hasPaidPlan ? ( - + {t("or").toLowerCase()} + onHelpItemSelect()} + className="hover:text-emphasis text-defualt font-medium underline" + href="https://cal.com/docs" + target="_blank" + rel="noreferrer"> + {t("browse_our_docs")} + + . +
+ {/* visible on mobile */} +
+

{t("specific_issue")}

+ - ) : ( - - {t("community_support")} - - )} + onHelpItemSelect(); + }}> + {t("contact_support")} + {t("or").toLowerCase()} onHelpItemSelect()} diff --git a/packages/features/ee/support/lib/intercom/IntercomMenuItem.tsx b/packages/features/ee/support/lib/intercom/IntercomMenuItem.tsx deleted file mode 100644 index ee8348fd68..0000000000 --- a/packages/features/ee/support/lib/intercom/IntercomMenuItem.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useLocale } from "@calcom/lib/hooks/useLocale"; - -import { useIntercom } from "./useIntercom"; - -interface IntercomMenuItemProps { - onHelpItemSelect: () => void; -} - -export default function IntercomMenuItem(props: IntercomMenuItemProps) { - const { onHelpItemSelect } = props; - const { t } = useLocale(); - const { open } = useIntercom(); - // eslint-disable-next-line turbo/no-undeclared-env-vars - if (!process.env.NEXT_PUBLIC_INTERCOM_APP_ID) return null; - - return ( - - ); -} diff --git a/packages/features/ee/support/lib/intercom/useIntercom.ts b/packages/features/ee/support/lib/intercom/useIntercom.ts index b96ad74800..3eeac1823b 100644 --- a/packages/features/ee/support/lib/intercom/useIntercom.ts +++ b/packages/features/ee/support/lib/intercom/useIntercom.ts @@ -17,6 +17,7 @@ const useIntercomHook = isInterComEnabled return { boot: noop, show: noop, + shutdown: noop, }; }; @@ -26,6 +27,37 @@ export const useIntercom = () => { const { hasPaidPlan } = useHasPaidPlan(); const { hasTeamPlan } = useHasTeamPlan(); + const boot = async () => { + let userHash; + + const req = await fetch(`/api/intercom-hash`); + const res = await req.json(); + if (res?.hash) { + userHash = res.hash; + } + + hookData.boot({ + ...(data && data?.name && { name: data.name }), + ...(data && data?.email && { email: data.email }), + ...(data && data?.id && { userId: data.id }), + createdAt: String(dayjs(data?.createdDate).unix()), + ...(userHash && { userHash }), + customAttributes: { + //keys should be snake cased + user_name: data?.username, + link: `${WEBSITE_URL}/${data?.username}`, + admin_link: `${WEBAPP_URL}/settings/admin/users/${data?.id}/edit`, + identity_provider: data?.identityProvider, + timezone: data?.timeZone, + locale: data?.locale, + has_paid_plan: hasPaidPlan, + has_team_plan: hasTeamPlan, + metadata: data?.metadata, + is_logged_in: !!data, + }, + }); + }; + const open = async () => { let userHash; @@ -57,7 +89,7 @@ export const useIntercom = () => { }); hookData.show(); }; - return { ...hookData, open }; + return { ...hookData, open, boot }; }; export default useIntercom; diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx index 4636bb7f9a..634de101d9 100644 --- a/packages/features/shell/Shell.tsx +++ b/packages/features/shell/Shell.tsx @@ -19,6 +19,7 @@ import { } from "@calcom/features/ee/organizations/components/OrgUpgradeBanner"; import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains"; import HelpMenuItem from "@calcom/features/ee/support/components/HelpMenuItem"; +import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom"; import { TeamsUpgradeBanner, type TeamsUpgradeBannerProps } from "@calcom/features/ee/teams/components"; import { useFlagMap } from "@calcom/features/flags/context/provider"; import { KBarContent, KBarRoot, KBarTrigger } from "@calcom/features/kbar/Kbar"; @@ -52,8 +53,10 @@ import { useFormbricks } from "@calcom/lib/formbricks-client"; import getBrandColours from "@calcom/lib/getBrandColours"; import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; import useTheme from "@calcom/lib/hooks/useTheme"; import { isKeyInObject } from "@calcom/lib/isKeyInObject"; +import { localStorage } from "@calcom/lib/webstorage"; import type { User } from "@calcom/prisma/client"; import { trpc } from "@calcom/trpc/react"; import useEmailVerifyCheck from "@calcom/trpc/react/hooks/useEmailVerifyCheck"; @@ -213,8 +216,16 @@ const useBanners = () => { const Layout = (props: LayoutProps) => { const banners = useBanners(); + const showIntercom = localStorage.getItem("showIntercom"); + const isMobile = useMediaQuery("(max-width: 768px)"); + const { boot } = useIntercom(); const pageTitle = typeof props.heading === "string" && !props.title ? props.heading : props.title; + useEffect(() => { + if (showIntercom === "false" || isMobile) return; + boot(); + }, [showIntercom, isMobile]); + const bannersHeight = useMemo(() => { const activeBanners = banners &&