feat(BOOK-67): Added functionality to show/hide the chatbot

Approved-by: Linus Flood
This commit is contained in:
Erik Tiekstra
2025-10-16 10:59:47 +00:00
parent 69a1b5f213
commit 800df0ade9
13 changed files with 147 additions and 72 deletions

View File

@@ -31,6 +31,7 @@
--back-to-top-button: 80;
--language-switcher-z-index: 85;
--sidepeek-z-index: 100;
--chatbot-z-index: 149;
--lightbox-z-index: 150;
--default-modal-overlay-z-index: 100;
--default-modal-z-index: 101;
@@ -73,6 +74,15 @@ body.overflow-hidden {
border-width: 0;
}
#kindly-chat-api {
z-index: var(--chatbot-z-index);
}
/* Hide chat widget when booking widget is open */
body:has([data-booking-widget-open="true"]) #kindly-chat-api {
z-index: -1 !important;
}
@media screen and (min-width: 768px) {
:root {
--max-width-single-spacing: var(--Layout-Tablet-Margin-Margin-min);

View File

@@ -0,0 +1,54 @@
"use client"
import { usePathname, useSearchParams } from "next/navigation"
import Script from "next/script"
import { useEffect } from "react"
import { shouldShowChatbot } from "@/components/ChatbotScript/utils"
import useLang from "@/hooks/useLang"
interface ChatbotClientProps {
liveLangs: string[]
}
export function ChatbotClient({ liveLangs }: ChatbotClientProps) {
const lang = useLang()
const pathname = usePathname()
const searchParams = useSearchParams()
const currentLang = useLang()
const isLive = liveLangs.includes(currentLang)
const shouldShow =
isLive && shouldShowChatbot(pathname, searchParams, currentLang)
useEffect(() => {
window.kindlyOptions = {
position: {
bottom: "130px",
right: "20px",
},
}
}, [])
useEffect(() => {
if (window.kindlyChat) {
if (!shouldShow) {
window.kindlyChat.closeChat()
window.kindlyChat.hideBubble()
} else {
window.kindlyChat.showBubble()
}
}
}, [shouldShow])
return (
<Script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="910bd27a-7472-43a1-bcfc-955b41adc3e7"
data-shadow-dom
data-bubble-hidden={!shouldShow}
data-language={lang}
defer
></Script>
)
}

View File

@@ -1,34 +0,0 @@
"use client"
import { usePathname } from "next/navigation"
import { useEffect } from "react"
import useLang from "@/hooks/useLang"
import { CHATBOT_HIDE_ROUTES } from "./constants"
interface ChatbotRouteChangeProps {
liveLangs: string[]
}
export function ChatbotRouteChange({ liveLangs }: ChatbotRouteChangeProps) {
const pathName = usePathname()
const currentLang = useLang()
useEffect(() => {
const isLive = liveLangs.includes(currentLang)
const shouldHideChatbot = CHATBOT_HIDE_ROUTES.some((route) =>
pathName.includes(route)
)
if (window.kindlyChat) {
if (shouldHideChatbot || !isLive) {
window.kindlyChat.closeChat()
window.kindlyChat.hideBubble()
} else {
window.kindlyChat.showBubble()
}
}
}, [pathName, liveLangs, currentLang])
return null
}

View File

@@ -1 +1,18 @@
export const CHATBOT_HIDE_ROUTES = ["/hotelreservation"]
import { Lang } from "@scandic-hotels/common/constants/language"
export const CHATBOT_SHOW_ROUTES = {
[Lang.en]: [
"/customer-service", // Customer service pages
"/scandic-friends", // My pages
"/hotels", // Hotel pages
],
[Lang.sv]: [],
[Lang.no]: [],
[Lang.fi]: [],
[Lang.da]: [],
[Lang.de]: [],
} as const
export const CHATBOT_HIDE_CONDITIONS = {
searchParams: [{ key: "view", value: "map" }],
} as const

View File

@@ -1,33 +1,9 @@
import Script from "next/script"
import { env } from "@/env/server"
import { CHATBOT_HIDE_ROUTES } from "@/components/ChatbotScript/constants"
import { ChatbotRouteChange } from "@/components/ChatbotScript/RouteChange"
import { getLang } from "@/i18n/serverContext"
import { getPathname } from "@/utils/getPathname"
import { ChatbotClient } from "@/components/ChatbotScript/Client"
export default async function ChatbotScript() {
const lang = await getLang()
const liveLangs = env.CHATBOT_LIVE_LANGS
const pathName = await getPathname()
const isLive = liveLangs.includes(lang)
const shouldHideChatbot = CHATBOT_HIDE_ROUTES.some((route) =>
pathName.includes(route)
)
return (
<>
<Script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="910bd27a-7472-43a1-bcfc-955b41adc3e7"
data-shadow-dom
data-bubble-hidden={!isLive || shouldHideChatbot}
data-language={lang}
defer
></Script>
<ChatbotRouteChange liveLangs={liveLangs} />
</>
)
return <ChatbotClient liveLangs={liveLangs} />
}

View File

@@ -0,0 +1,42 @@
import {
removeMultipleSlashes,
removeTrailingSlash,
} from "@scandic-hotels/common/utils/url"
import { CHATBOT_HIDE_CONDITIONS, CHATBOT_SHOW_ROUTES } from "./constants"
import type { Lang } from "@scandic-hotels/common/constants/language"
export function shouldShowChatbot(
pathname: string,
searchParams: URLSearchParams | null,
lang: Lang
): boolean {
const cleanPathname = removeTrailingSlash(removeMultipleSlashes(pathname))
const isOnShowRoute = CHATBOT_SHOW_ROUTES[lang].some((route) => {
const fullRoute = removeTrailingSlash(
removeMultipleSlashes(`/${lang}${route}`)
)
return cleanPathname.startsWith(fullRoute)
})
const isOnStartPage = cleanPathname === `/${lang}`
if (!isOnShowRoute && !isOnStartPage) {
return false
}
if (searchParams) {
const shouldHideOnSearchParams = CHATBOT_HIDE_CONDITIONS.searchParams.some(
({ key, value }) => {
const paramValue = searchParams.get(key)
return paramValue === value
}
)
if (shouldHideOnSearchParams) {
return false
}
}
return true
}

View File

@@ -23,4 +23,10 @@ interface Window {
showChat: () => void
hideBubble: () => void
}
kindlyOptions: {
position?: {
bottom?: string
right?: string
}
}
}