@@ -12,6 +12,7 @@ import { sendGAEvent } from "@next/third-parties/google";
1212
1313// Types
1414type PrefillAIAgentEvent = CustomEvent < { message : string } > ;
15+ type ShowFollowUpMessagesEvent = CustomEvent < { sessionId : string } > ;
1516
1617type TMessageResponse = {
1718 messages : TMessage [ ] ;
@@ -156,6 +157,27 @@ const fetchAskStream = async (
156157 }
157158} ;
158159
160+ const fetchFollowUpMessages = async ( sessionId : string ) : Promise < string [ ] > => {
161+ const url = new URL (
162+ `${ String ( process . env . NEXT_PUBLIC_LANDING_GET_FOLLOWUP_WEBHOOK ) } `
163+ ) ;
164+ url . searchParams . set ( "sessionId" , sessionId ) ;
165+
166+ const response = await fetch ( url , {
167+ method : "GET" ,
168+ headers : {
169+ "Content-Type" : "application/json"
170+ }
171+ } ) ;
172+
173+ if ( ! response . ok ) {
174+ return [ ] ;
175+ }
176+
177+ const data = await response . json ( ) ;
178+ return data . data ;
179+ } ;
180+
159181// Cookies
160182function setCookie ( cname : string , cvalue : string , exdays : number ) {
161183 const d = new Date ( ) ;
@@ -193,6 +215,7 @@ interface HyperBotToggleProps {
193215export default function LandingAIAgent ( { gaEvent } : HyperBotToggleProps ) {
194216 const [ sessionId , setSessionId ] = useState < string | undefined > ( undefined ) ;
195217 const [ messages , setMessages ] = useState < TMessage [ ] > ( [ ] ) ;
218+ const [ followUpMessages , setFollowUpMessages ] = useState < string [ ] > ( [ ] ) ;
196219 const [ text , setText ] = useState < string > ( "" ) ;
197220 const [ isSubmitting , setIsSubmitting ] = useState < boolean > ( false ) ;
198221
@@ -259,6 +282,17 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
259282 scrollToBottom ( ) ;
260283 } , [ messages ] ) ;
261284
285+ // Effect to scroll to bottom when follow-up messages are loaded
286+ useEffect ( ( ) => {
287+ if ( ! chatContainerRef . current ) return ;
288+ if ( followUpMessages . length === 0 ) return ;
289+
290+ // Use requestAnimationFrame to ensure DOM has updated
291+ requestAnimationFrame ( ( ) => {
292+ scrollToBottom ( ) ;
293+ } ) ;
294+ } , [ followUpMessages ] ) ;
295+
262296 // Effect to lock body scroll on mobile when chat is open
263297 useEffect ( ( ) => {
264298 // Only apply on mobile (< 720px)
@@ -291,6 +325,10 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
291325 inputRef . current . value = "" ;
292326 }
293327
328+ // Set follow up messages to be empty
329+ // as it will be populated again when the AI agent responds
330+ setFollowUpMessages ( [ ] ) ;
331+
294332 setIsSubmitting ( true ) ;
295333 try {
296334 const prevMessages = messages ;
@@ -332,6 +370,9 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
332370 toast ( "Failed to ask question. Please try again later." ) ;
333371 } finally {
334372 setIsSubmitting ( false ) ;
373+ window . dispatchEvent (
374+ new CustomEvent ( "showFollowUpMessages" , { detail : { sessionId } } )
375+ ) ;
335376 }
336377 } ,
337378 [ messages , sessionId ]
@@ -358,6 +399,33 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
358399 } ;
359400 } , [ handleSubmit ] ) ;
360401
402+ // Listen for custom event to show follow up messages
403+ useEffect ( ( ) => {
404+ const handleShowFollowUpMessages = ( event : Event ) => {
405+ const customEvent = event as ShowFollowUpMessagesEvent ;
406+ const { sessionId } = customEvent . detail ;
407+
408+ if ( sessionId ) {
409+ fetchFollowUpMessages ( sessionId )
410+ . then ( ( followUpMessages ) => {
411+ setFollowUpMessages ( followUpMessages ) ;
412+ } )
413+ . catch ( ( ) => {
414+ setFollowUpMessages ( [ ] ) ;
415+ } ) ;
416+ }
417+ } ;
418+
419+ window . addEventListener ( "showFollowUpMessages" , handleShowFollowUpMessages ) ;
420+
421+ return ( ) => {
422+ window . removeEventListener (
423+ "showFollowUpMessages" ,
424+ handleShowFollowUpMessages
425+ ) ;
426+ } ;
427+ } , [ sessionId ] ) ;
428+
361429 return (
362430 < >
363431 { /* Chat window with animation */ }
@@ -408,6 +476,28 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
408476 ) }
409477 </ div >
410478 ) ) }
479+
480+ { /* Follow up messages */ }
481+ { followUpMessages . length > 0 && ! isSubmitting && (
482+ < div className = "flex flex-col gap-2" >
483+ < p className = "text-sm font-medium text-gray-800" > Follow up</ p >
484+ { followUpMessages . map ( ( text , id ) => (
485+ < button
486+ key = { id }
487+ type = "button"
488+ className = "cursor-pointer text-left text-sm whitespace-normal text-gray-600 hover:underline"
489+ onClick = { ( ) => {
490+ window . dispatchEvent (
491+ new CustomEvent ( "prefillAIAgent" , {
492+ detail : { message : text }
493+ } )
494+ ) ;
495+ } } >
496+ { text }
497+ </ button >
498+ ) ) }
499+ </ div >
500+ ) }
411501 </ div >
412502
413503 { /* Input */ }
@@ -421,8 +511,11 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
421511 disabled = { isSubmitting }
422512 className = "rounded-md border border-gray-400 bg-transparent text-gray-600 hover:cursor-pointer"
423513 onClick = { ( ) => {
424- setText ( text ) ;
425- inputRef . current ?. focus ( ) ;
514+ window . dispatchEvent (
515+ new CustomEvent ( "prefillAIAgent" , {
516+ detail : { message : text }
517+ } )
518+ ) ;
426519 } } >
427520 { text }
428521 </ Button >
@@ -473,8 +566,11 @@ export default function LandingAIAgent({ gaEvent }: HyperBotToggleProps) {
473566 disabled = { isSubmitting }
474567 className = "rounded-md border border-gray-200 bg-transparent text-gray-600 hover:cursor-pointer"
475568 onClick = { ( ) => {
476- setText ( text ) ;
477- inputRef . current ?. focus ( ) ;
569+ window . dispatchEvent (
570+ new CustomEvent ( "prefillAIAgent" , {
571+ detail : { message : text }
572+ } )
573+ ) ;
478574 } } >
479575 { text }
480576 </ Button >
0 commit comments