diff --git a/client/landing/stepper/declarative-flow/hundred-year-plan.ts b/client/landing/stepper/declarative-flow/hundred-year-plan.ts index 9c722015de1d0..2b2daf23c7a80 100644 --- a/client/landing/stepper/declarative-flow/hundred-year-plan.ts +++ b/client/landing/stepper/declarative-flow/hundred-year-plan.ts @@ -39,6 +39,11 @@ const HundredYearPlanFlow: Flow = { asyncComponent: () => import( './internals/steps-repository/hundred-year-plan-diy-or-difm' ), }, + { + slug: 'schedule-appointment', + asyncComponent: () => + import( './internals/steps-repository/hundred-year-plan-schedule-appointment' ), + }, ] : [] ), @@ -119,7 +124,9 @@ const HundredYearPlanFlow: Flow = { return navigate( hasSite ? 'new-or-existing-site' : 'setup' ); } // TODO: add VIP flow - return navigate( hasSite ? 'new-or-existing-site' : 'setup' ); + return navigate( 'schedule-appointment' ); + case 'schedule-appointment': + return navigate( 'thank-you' ); case 'new-or-existing-site': if ( 'new-site' === providedDependencies?.newExistingSiteChoice ) { return navigate( 'setup' ); diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/index.tsx new file mode 100644 index 0000000000000..4a0905d19ae1c --- /dev/null +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/index.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, useMemo } from 'react'; + +declare global { + interface Window { + Calendly: any; + } +} + +interface PrefillData { + name?: string; + email?: string; + // Add other prefill fields as needed +} + +interface CalendlyWidgetProps { + url: string; + id?: string; + prefill?: PrefillData; + onSchedule?: () => void; +} + +const CALENDLY_SCRIPT_URL = 'https://assets.calendly.com/assets/external/widget.js'; + +function isCalendlyEvent( e: MessageEvent ): boolean { + return ( + e.origin === 'https://calendly.com' && e.data.event && e.data.event.indexOf( 'calendly.' ) === 0 + ); +} + +const CalendlyWidget: React.FC< CalendlyWidgetProps > = ( { url, id, prefill, onSchedule } ) => { + const widgetId = useMemo( + () => id || `calendly-widget-${ Math.random().toString( 36 ).substr( 2, 9 ) }`, + [ id ] + ); + + useEffect( () => { + const handleMessage = ( e: MessageEvent ) => { + if ( isCalendlyEvent( e ) && e.data.event === 'calendly.event_scheduled' ) { + onSchedule?.(); + } + }; + + window.addEventListener( 'message', handleMessage ); + return () => window.removeEventListener( 'message', handleMessage ); + }, [ onSchedule ] ); + + useEffect( () => { + // Check if the script is already loaded + if ( ! document.querySelector( `script[src="${ CALENDLY_SCRIPT_URL }"]` ) ) { + const script = document.createElement( 'script' ); + script.src = CALENDLY_SCRIPT_URL; + script.async = true; + document.body.appendChild( script ); + } + + const loadCalendly = async () => { + while ( typeof window.Calendly === 'undefined' || ! url ) { + await new Promise( ( resolve ) => setTimeout( resolve, 100 ) ); + } + + const element = document.getElementById( widgetId ); + if ( element ) { + // Clear out the container div when props change. + element.innerHTML = ''; + window.Calendly.initInlineWidget( { + url: `https://calendly.com/${ url }`, + parentElement: document.getElementById( widgetId ), + prefill: prefill || {}, + utm: {}, + } ); + } + }; + + loadCalendly(); + + // Cleanup function + return () => { + const existingScript = document.querySelector( `script[src="${ CALENDLY_SCRIPT_URL }"]` ); + if ( existingScript ) { + existingScript.remove(); + } + }; + }, [ url, widgetId, prefill ] ); + + return
; +}; + +export default CalendlyWidget; diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/style.scss b/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/style.scss new file mode 100644 index 0000000000000..5c8534a694b81 --- /dev/null +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/components/calendy-widget/style.scss @@ -0,0 +1,4 @@ +.calendly-widget { + min-width: 320px; + height: 630px; +} \ No newline at end of file diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/hundred-year-plan-schedule-appointment/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/hundred-year-plan-schedule-appointment/index.tsx new file mode 100644 index 0000000000000..92571bb40826a --- /dev/null +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/hundred-year-plan-schedule-appointment/index.tsx @@ -0,0 +1,69 @@ +import { UserSelect } from '@automattic/data-stores'; +import { useSelect } from '@wordpress/data'; +import { useTranslate } from 'i18n-calypso'; +import FormattedHeader from 'calypso/components/formatted-header'; +import { USER_STORE } from '../../../../stores'; +import CalendlyWidget from '../components/calendy-widget'; +import HundredYearPlanStepWrapper from '../hundred-year-plan-step-wrapper'; +import type { Step } from '../../types'; + +import './styles.scss'; + +declare global { + interface Window { + Calendly: any; + } +} + +const CALENDLY_ID = 'tim-broddin-a8c/30min'; + +const HundredYearPlanScheduleAppointment: Step = function HundredYearPlanScheduleAppointment( { + navigation, + flow, +} ) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { submit } = navigation; + const translate = useTranslate(); + + const currentUser = useSelect( + ( select ) => ( select( USER_STORE ) as UserSelect ).getCurrentUser(), + [] + ); + + return ( +