feat(forms): add isolated Form A consultation testing
This commit is contained in:
25 files changed
+1046
-253
No files matched your search
@@ -1,20 +1,41 @@
|
||||
---
|
||||
import Button from './Button.astro';
|
||||
import ContactObfuscation from './ContactObfuscation.astro';
|
||||
import JotformIframe from './JotformIframe.astro';
|
||||
import { formMessages } from '../utils/form-messages';
|
||||
import { formModeForRuntime, resolveFormMode, resolveMockFormResult, type LogicalForm } from '../utils/form-integration';
|
||||
const { lang = 'en', showBackground = false } = Astro.props;
|
||||
import { formModeForRuntime, resolveFormAIframe, resolveFormMode, resolveMockFormResult, type LogicalForm } from '../utils/form-integration';
|
||||
const { lang = 'en', showBackground = false, route = '' } = Astro.props;
|
||||
const text = formMessages(lang);
|
||||
const title = Astro.props.title ?? text.heading;
|
||||
const logicalForm: LogicalForm = Astro.props.logicalForm ?? (Astro.props.title === 'Physician & Insurer Referrals' ? 'referral' : 'service');
|
||||
const config = resolveFormMode(import.meta.env.PUBLIC_AIA_FORMS_MODE, import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED);
|
||||
const mode = formModeForRuntime(config);
|
||||
const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_RESULT);
|
||||
const formAIframe = logicalForm === 'service'
|
||||
? resolveFormAIframe({
|
||||
rawMode: import.meta.env.PUBLIC_AIA_FORMS_MODE,
|
||||
liveApproved: import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED,
|
||||
isolatedTestApproved: import.meta.env.PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED,
|
||||
consultationTestApproved: import.meta.env.PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED,
|
||||
productionApproved: import.meta.env.PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED,
|
||||
environmentRole: import.meta.env.PUBLIC_AIA_FORMS_ENVIRONMENT,
|
||||
allowIndexing: import.meta.env.PUBLIC_ALLOW_INDEXING,
|
||||
route,
|
||||
locale: lang,
|
||||
})
|
||||
: undefined;
|
||||
const consultationIframeEnabled = formAIframe?.enabled && formAIframe.context === 'consultation';
|
||||
const consultationHeading = lang === 'es' ? 'Comience una conversación' : 'Start a conversation';
|
||||
const consultationDescription = lang === 'es'
|
||||
? 'Use este formulario para solicitar una conversación. Un defensor de clientes de AIA puede explicarle los próximos pasos.'
|
||||
: 'Use this form to request a conversation. An AIA client advocate can explain the next steps.';
|
||||
---
|
||||
<section class:list={['form-section', { 'form-section-background': showBackground }]} aria-labelledby="form-title">
|
||||
<div class="container form-grid">
|
||||
<div><p class="eyebrow">{text.eyebrow}</p><h2 id="form-title">{title}</h2><p>{text.intro}</p></div>
|
||||
<div class="form" role="group" data-aia-form data-form-mode={mode} data-form-mode-reason={config.reason} data-logical-form={logicalForm} data-mock-result={mockResult} data-mock-success={text.mockSuccess} data-mock-failed={text.mockFailed} data-mock-unavailable={text.mockUnavailable}>
|
||||
{formAIframe && consultationIframeEnabled
|
||||
? <JotformIframe config={formAIframe} heading={consultationHeading} description={consultationDescription} />
|
||||
: <div class="form" role="group" data-aia-form data-form-mode={mode} data-form-mode-reason={config.reason} data-logical-form={logicalForm} data-mock-result={mockResult} data-mock-success={text.mockSuccess} data-mock-failed={text.mockFailed} data-mock-unavailable={text.mockUnavailable}>
|
||||
<label>{text.name}<input name="name" autocomplete="name" disabled={mode === 'off'} /></label>
|
||||
<label>{text.email}<input type="email" name="email" autocomplete="email" disabled={mode === 'off'} /></label>
|
||||
<label>{text.phone}<input type="tel" name="phone" autocomplete="tel" disabled={mode === 'off'} /></label>
|
||||
@@ -22,7 +43,7 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
<label>{text.message}<textarea name="message" rows="5" disabled={mode === 'off'}></textarea></label>
|
||||
<Button type="button" data-mock-submit disabled={mode === 'off'} aria-describedby="form-note">{text.submit}</Button>
|
||||
<p id="form-note" class="form-note" data-form-status>{mode === 'mock' ? text.mock : <>{text.disabled} <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</>}</p>
|
||||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -5,32 +5,40 @@ interface Props {
|
||||
config: FormAIframeConfig;
|
||||
heading: string;
|
||||
description?: string;
|
||||
variant?: 'standalone' | 'embedded';
|
||||
variant?: 'standalone' | 'embedded' | 'drawer';
|
||||
deferUntilActivated?: boolean;
|
||||
hideHeading?: boolean;
|
||||
}
|
||||
|
||||
const { config, heading, description, variant = 'standalone' } = Astro.props;
|
||||
const { config, heading, description, variant = 'standalone', deferUntilActivated = false, hideHeading = false } = Astro.props;
|
||||
|
||||
if (!config.enabled || !config.url || !config.title || !config.fallbackText || !config.fallbackLinkText) {
|
||||
throw new Error('JotformIframe requires an enabled, fully validated Form A iframe configuration.');
|
||||
}
|
||||
|
||||
const idBase = `jotform-form-a-${config.route.replaceAll('/', '-').replaceAll(/^-+|-+$/g, '')}-${config.context}`;
|
||||
const headingId = `${idBase}-heading`;
|
||||
---
|
||||
|
||||
<section
|
||||
class:list={['jotform-iframe', { 'jotform-iframe--embedded': variant === 'embedded' }]}
|
||||
class:list={['jotform-iframe', { 'jotform-iframe--embedded': variant === 'embedded', 'jotform-iframe--drawer': variant === 'drawer' }]}
|
||||
role="group"
|
||||
aria-labelledby="jotform-iframe-heading"
|
||||
aria-labelledby={hideHeading ? undefined : headingId}
|
||||
aria-label={hideHeading ? config.title : undefined}
|
||||
data-jotform-form-a
|
||||
data-form-mode={config.mode}
|
||||
data-form-environment={config.environmentRole}
|
||||
data-logical-form="general"
|
||||
data-logical-form={config.context === 'consultation' ? 'service' : 'general'}
|
||||
data-form-context={config.context}
|
||||
data-jotform-source="approved-form-a"
|
||||
data-jotform-deferred={deferUntilActivated ? 'true' : undefined}
|
||||
>
|
||||
<h3 id="jotform-iframe-heading" class="jotform-iframe__heading">{heading}</h3>
|
||||
{!hideHeading && <h3 id={headingId} class="jotform-iframe__heading">{heading}</h3>}
|
||||
{description && <p class="jotform-iframe__description">{description}</p>}
|
||||
<iframe
|
||||
class="jotform-iframe__frame"
|
||||
src={config.url}
|
||||
src={deferUntilActivated ? undefined : config.url}
|
||||
data-jotform-iframe-url={deferUntilActivated ? config.url : undefined}
|
||||
title={config.title}
|
||||
loading="eager"
|
||||
referrerpolicy="no-referrer"
|
||||
@@ -65,6 +73,7 @@ if (!config.enabled || !config.url || !config.title || !config.fallbackText || !
|
||||
fallback.hidden = true;
|
||||
|
||||
let disposed = false;
|
||||
let activated = false;
|
||||
const hideFallback = () => {
|
||||
fallback.hidden = true;
|
||||
container.dataset.jotformFallback = 'hidden';
|
||||
@@ -74,20 +83,37 @@ if (!config.enabled || !config.url || !config.title || !config.fallbackText || !
|
||||
fallback.hidden = false;
|
||||
container.dataset.jotformFallback = 'visible';
|
||||
};
|
||||
const timer = window.setTimeout(showFallback, fallbackTimeoutMs);
|
||||
let timer;
|
||||
const onLoad = () => {
|
||||
window.clearTimeout(timer);
|
||||
if (timer) window.clearTimeout(timer);
|
||||
// A late frame load supersedes the transport timeout. It is still not
|
||||
// treated as a success, conversion, or cross-origin health signal.
|
||||
hideFallback();
|
||||
};
|
||||
const dispose = () => {
|
||||
disposed = true;
|
||||
window.clearTimeout(timer);
|
||||
if (timer) window.clearTimeout(timer);
|
||||
frame.removeEventListener('load', onLoad);
|
||||
container.removeEventListener('aia:jotform-activate', activate);
|
||||
};
|
||||
|
||||
frame.addEventListener('load', onLoad, { once: true });
|
||||
const activate = () => {
|
||||
if (disposed || activated) return;
|
||||
const deferred = container.dataset.jotformDeferred === 'true';
|
||||
const approvedUrl = frame.dataset.jotformIframeUrl;
|
||||
if (deferred && !approvedUrl) return;
|
||||
activated = true;
|
||||
frame.addEventListener('load', onLoad, { once: true });
|
||||
timer = window.setTimeout(showFallback, fallbackTimeoutMs);
|
||||
if (deferred) frame.src = approvedUrl;
|
||||
container.dataset.jotformIframeActivated = 'true';
|
||||
};
|
||||
|
||||
if (container.dataset.jotformDeferred === 'true') {
|
||||
container.addEventListener('aia:jotform-activate', activate, { once: true });
|
||||
} else {
|
||||
activate();
|
||||
}
|
||||
window.addEventListener('pagehide', dispose, { once: true });
|
||||
document.addEventListener('astro:before-swap', dispose, { once: true });
|
||||
};
|
||||
@@ -184,6 +210,22 @@ if (!config.enabled || !config.url || !config.title || !config.fallbackText || !
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.jotform-iframe--drawer {
|
||||
--jotform-frame-height: 72rem;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.jotform-iframe--drawer .jotform-iframe__heading {
|
||||
border: 0;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.jotform-iframe__frame {
|
||||
height: 68rem;
|
||||
@@ -194,5 +236,10 @@ if (!config.enabled || !config.url || !config.title || !config.fallbackText || !
|
||||
height: 50rem;
|
||||
min-height: 50rem;
|
||||
}
|
||||
|
||||
.jotform-iframe--drawer .jotform-iframe__frame {
|
||||
height: 82rem;
|
||||
min-height: 82rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,189 +1,299 @@
|
||||
---
|
||||
import ContactObfuscation from './ContactObfuscation.astro';
|
||||
import { formModeForRuntime, resolveFormMode, resolveMockFormResult } from '../utils/form-integration';
|
||||
import JotformIframe from './JotformIframe.astro';
|
||||
import {
|
||||
formModeForRuntime,
|
||||
resolveFormAIframe,
|
||||
resolveFormMode,
|
||||
resolveMockFormResult,
|
||||
} from '../utils/form-integration';
|
||||
|
||||
type ServiceKey = 'aba-therapy' | 'autism-evaluations' | 'learner-social-club';
|
||||
type SupportedLocale = 'en' | 'es';
|
||||
|
||||
interface Props {
|
||||
service: ServiceKey;
|
||||
lang: SupportedLocale;
|
||||
route: string;
|
||||
}
|
||||
|
||||
const serviceCopy: Record<ServiceKey, {
|
||||
heading: string[];
|
||||
serviceName: string;
|
||||
statusLead: string;
|
||||
status: string;
|
||||
prompt: string;
|
||||
}> = {
|
||||
'aba-therapy': {
|
||||
heading: ['No WAITLIST!'],
|
||||
serviceName: 'ABA Therapy',
|
||||
statusLead: 'is',
|
||||
status: 'currently accepting new patients',
|
||||
prompt: "To help guarantee your child's admission to our program, please provide their information."
|
||||
const serviceNames: Record<SupportedLocale, Record<ServiceKey, string>> = {
|
||||
en: {
|
||||
'aba-therapy': 'ABA Therapy',
|
||||
'autism-evaluations': 'Autism Evaluations',
|
||||
'learner-social-club': 'Learner Social Club',
|
||||
},
|
||||
'autism-evaluations': {
|
||||
heading: ['Enrollment', 'Now Open'],
|
||||
serviceName: 'Autism Evaluations',
|
||||
statusLead: 'are',
|
||||
status: 'now open for enrollment',
|
||||
prompt: "To help guarantee your child's admission into one of our upcoming programs, please provide their information."
|
||||
es: {
|
||||
'aba-therapy': 'Terapia ABA',
|
||||
'autism-evaluations': 'Evaluaciones de autismo',
|
||||
'learner-social-club': 'Learner Social Club',
|
||||
},
|
||||
'learner-social-club': {
|
||||
heading: ['Enrollment', 'Now Open'],
|
||||
serviceName: 'Learner Social Club',
|
||||
statusLead: 'is',
|
||||
status: 'now open for enrollment',
|
||||
prompt: "To help guarantee your child's spot in one of our upcoming group enrichment programs, please provide their information."
|
||||
}
|
||||
};
|
||||
|
||||
const { service } = Astro.props;
|
||||
const copy = serviceCopy[service];
|
||||
const drawerId = `service-inquiry-${service}`;
|
||||
const drawerCopy: Record<SupportedLocale, {
|
||||
open: (service: string) => string;
|
||||
heading: (service: string) => string;
|
||||
introduction: string;
|
||||
privacy: string;
|
||||
close: string;
|
||||
noScript: string;
|
||||
hostedLink: string;
|
||||
legacyStatus: string;
|
||||
legacyPrompt: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
childFirstName: string;
|
||||
childLastName: string;
|
||||
childBirthDate: string;
|
||||
location: string;
|
||||
service: string;
|
||||
payment: string;
|
||||
referral: string;
|
||||
comments: string;
|
||||
select: string;
|
||||
submit: string;
|
||||
disabled: string;
|
||||
mock: string;
|
||||
}> = {
|
||||
en: {
|
||||
open: (service) => `Talk with AIA about ${service}`,
|
||||
heading: (service) => `Talk with AIA about ${service}`,
|
||||
introduction: 'Use this form to request a conversation. An AIA client advocate can explain the next steps.',
|
||||
privacy: 'Please use this form only for general contact information. AIA can discuss any needed details during follow-up.',
|
||||
close: 'Close consultation form',
|
||||
noScript: 'To request a conversation,',
|
||||
hostedLink: 'open the consultation form in a new tab.',
|
||||
legacyStatus: 'An AIA client advocate can discuss this service and possible next steps.',
|
||||
legacyPrompt: 'Online submission is not yet connected. Please call AIA to begin a conversation.',
|
||||
firstName: 'First name',
|
||||
lastName: 'Last name',
|
||||
phone: 'Phone number',
|
||||
email: 'Email',
|
||||
childFirstName: 'Child first name',
|
||||
childLastName: 'Child last name',
|
||||
childBirthDate: 'Child birth date',
|
||||
location: 'Location interest',
|
||||
service: 'Service interest',
|
||||
payment: 'Insurance and payment options',
|
||||
referral: 'How did you hear about us?',
|
||||
comments: 'Additional information or comments',
|
||||
select: 'Please select',
|
||||
submit: 'Submit',
|
||||
disabled: 'Online submission is not yet connected. Please call',
|
||||
mock: 'Demo only: this local fixture never sends information.',
|
||||
},
|
||||
es: {
|
||||
open: (service) => `Hable con AIA sobre ${service}`,
|
||||
heading: (service) => `Hable con AIA sobre ${service}`,
|
||||
introduction: 'Use este formulario para solicitar una conversación. Un defensor de clientes de AIA puede explicarle los próximos pasos.',
|
||||
privacy: 'Use este formulario solo para información general de contacto. AIA puede hablar sobre los detalles necesarios durante el seguimiento.',
|
||||
close: 'Cerrar el formulario de consulta',
|
||||
noScript: 'Para solicitar una conversación,',
|
||||
hostedLink: 'abra el formulario de consulta en una pestaña nueva.',
|
||||
legacyStatus: 'Un defensor de clientes de AIA puede hablar sobre este servicio y los próximos pasos posibles.',
|
||||
legacyPrompt: 'El envío en línea aún no está habilitado. Llame a AIA para iniciar una conversación.',
|
||||
firstName: 'Nombre',
|
||||
lastName: 'Apellido',
|
||||
phone: 'Número de teléfono',
|
||||
email: 'Correo electrónico',
|
||||
childFirstName: 'Nombre del niño o la niña',
|
||||
childLastName: 'Apellido del niño o la niña',
|
||||
childBirthDate: 'Fecha de nacimiento del niño o la niña',
|
||||
location: 'Ubicación de interés',
|
||||
service: 'Servicio de interés',
|
||||
payment: 'Opciones de seguro y pago',
|
||||
referral: '¿Cómo se enteró de nosotros?',
|
||||
comments: 'Información adicional o comentarios',
|
||||
select: 'Seleccione una opción',
|
||||
submit: 'Enviar',
|
||||
disabled: 'El envío en línea aún no está habilitado. Llame al',
|
||||
mock: 'Solo demostración: esta prueba local nunca envía información.',
|
||||
},
|
||||
};
|
||||
|
||||
const { service, lang, route } = Astro.props;
|
||||
const copy = drawerCopy[lang];
|
||||
const serviceName = serviceNames[lang][service];
|
||||
const drawerId = `service-inquiry-${lang}-${service}`;
|
||||
const titleId = `${drawerId}-title`;
|
||||
const noteId = `${drawerId}-note`;
|
||||
const config = resolveFormMode(import.meta.env.PUBLIC_AIA_FORMS_MODE, import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED);
|
||||
const mode = formModeForRuntime(config);
|
||||
const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_RESULT);
|
||||
const formAIframe = resolveFormAIframe({
|
||||
rawMode: import.meta.env.PUBLIC_AIA_FORMS_MODE,
|
||||
liveApproved: import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED,
|
||||
isolatedTestApproved: import.meta.env.PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED,
|
||||
consultationTestApproved: import.meta.env.PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED,
|
||||
productionApproved: import.meta.env.PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED,
|
||||
environmentRole: import.meta.env.PUBLIC_AIA_FORMS_ENVIRONMENT,
|
||||
allowIndexing: import.meta.env.PUBLIC_ALLOW_INDEXING,
|
||||
route,
|
||||
locale: lang,
|
||||
});
|
||||
const consultationTestEnabled = formAIframe.enabled && formAIframe.context === 'consultation';
|
||||
---
|
||||
|
||||
{consultationTestEnabled && formAIframe.url && <>
|
||||
<button
|
||||
class="service-inquiry-drawer__open"
|
||||
type="button"
|
||||
data-service-inquiry-open
|
||||
aria-controls={drawerId}
|
||||
aria-haspopup="dialog"
|
||||
>
|
||||
{copy.open(serviceName)}
|
||||
</button>
|
||||
<noscript>
|
||||
<p class="service-inquiry-drawer__noscript">
|
||||
{copy.noScript} <a href={formAIframe.url} target="_blank" rel="noopener noreferrer">{copy.hostedLink}</a>
|
||||
</p>
|
||||
</noscript>
|
||||
</>}
|
||||
|
||||
<dialog
|
||||
id={drawerId}
|
||||
class="service-inquiry-drawer"
|
||||
data-service-inquiry-drawer
|
||||
data-dismiss-key={`aia-service-inquiry-dismissed:${service}`}
|
||||
data-explicit-activation={consultationTestEnabled ? 'true' : undefined}
|
||||
data-dismiss-key={consultationTestEnabled ? undefined : `aia-service-inquiry-dismissed:${lang}:${service}`}
|
||||
aria-labelledby={titleId}
|
||||
>
|
||||
<button class="service-inquiry-drawer__close" type="button" data-service-inquiry-close aria-label="Close inquiry form">
|
||||
<button class="service-inquiry-drawer__close" type="button" data-service-inquiry-close aria-label={copy.close}>
|
||||
<svg aria-hidden="true" viewBox="0 0 32 32" width="18" height="18">
|
||||
<path d="M4 4 28 28M28 4 4 28" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="3" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<header class="service-inquiry-drawer__intro">
|
||||
<h2 id={titleId} data-service-inquiry-title tabindex="-1">
|
||||
{copy.heading.map((line, index) => <Fragment>{index > 0 && <br />}{line}</Fragment>)}
|
||||
</h2>
|
||||
<p>
|
||||
Arizona Institute for Autism's<br />
|
||||
<strong>{copy.serviceName}</strong><br />
|
||||
{copy.statusLead} <em>{copy.status}</em>.
|
||||
</p>
|
||||
<p>{copy.prompt}</p>
|
||||
<h2 id={titleId} data-service-inquiry-title tabindex="-1">{consultationTestEnabled ? copy.heading(serviceName) : serviceName}</h2>
|
||||
<p>{consultationTestEnabled ? copy.introduction : copy.legacyStatus}</p>
|
||||
{consultationTestEnabled && <p class="service-inquiry-drawer__privacy">{copy.privacy}</p>}
|
||||
</header>
|
||||
|
||||
<div class="service-inquiry-form" role="group" data-aia-form data-form-mode={mode} data-form-mode-reason={config.reason} data-logical-form="service" data-mock-result={mockResult} data-mock-success="Demo only: the local fixture completed without sending anything." data-mock-failed="Demo only: the local fixture simulated a failed submission." data-mock-unavailable="Demo only: the local fixture simulated an unavailable service.">
|
||||
<div class="service-inquiry-form__grid">
|
||||
<label>
|
||||
<span>First Name<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input name="first_name" autocomplete="given-name" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>Last Name<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input name="last_name" autocomplete="family-name" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>Phone Number<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<span class="service-inquiry-form__phone">
|
||||
<span class="service-inquiry-form__country">
|
||||
<span aria-hidden="true">🇺🇸</span>
|
||||
<span class="service-inquiry-form__country-caret" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">United States country code</span>
|
||||
{consultationTestEnabled
|
||||
? <div class="service-inquiry-drawer__iframe">
|
||||
<JotformIframe config={formAIframe} heading={copy.heading(serviceName)} variant="drawer" deferUntilActivated hideHeading />
|
||||
</div>
|
||||
: <div class="service-inquiry-form" role="group" data-aia-form data-form-mode={mode} data-form-mode-reason={config.reason} data-logical-form="service" data-mock-result={mockResult} data-mock-success="Demo only: the local fixture completed without sending anything." data-mock-failed="Demo only: the local fixture simulated a failed submission." data-mock-unavailable="Demo only: the local fixture simulated an unavailable service.">
|
||||
<div class="service-inquiry-form__grid">
|
||||
<label>
|
||||
<span>{copy.firstName}<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input name="first_name" autocomplete="given-name" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.lastName}<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input name="last_name" autocomplete="family-name" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.phone}<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<span class="service-inquiry-form__phone">
|
||||
<span class="service-inquiry-form__country">
|
||||
<span aria-hidden="true">🇺🇸</span>
|
||||
<span class="service-inquiry-form__country-caret" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">United States country code</span>
|
||||
</span>
|
||||
<span class="service-inquiry-form__phone-number">
|
||||
<span aria-hidden="true">+1</span>
|
||||
<input type="tel" name="phone" autocomplete="tel-national" required disabled={mode === 'off'} />
|
||||
</span>
|
||||
</span>
|
||||
<span class="service-inquiry-form__phone-number">
|
||||
<span aria-hidden="true">+1</span>
|
||||
<input type="tel" name="phone" autocomplete="tel-national" required disabled={mode === 'off'} />
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Email<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input type="email" name="email" autocomplete="email" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>Child First Name</span>
|
||||
<input name="child_first_name" autocomplete="off" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>Child Last Name</span>
|
||||
<input name="child_last_name" autocomplete="off" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label class="service-inquiry-form__wide">
|
||||
<span>Child Birth Date</span>
|
||||
<input name="child_birth_date" inputmode="numeric" autocomplete="bday" placeholder="MM - DD - YYYY" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>Location Interest</span>
|
||||
<select name="location_interest" disabled={mode === 'off'}>
|
||||
<option value="" selected>Please Select</option>
|
||||
<option value="aia_scottsdale">AIA Scottsdale</option>
|
||||
<option value="aia_glendale">AIA Glendale</option>
|
||||
<option value="other_none">Other/None</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Service Interest</span>
|
||||
<select name="service_interest" disabled={mode === 'off'}>
|
||||
<option value="" selected>Please Select</option>
|
||||
<option value="behavioral">Behavioral - ABA Therapy Service</option>
|
||||
<option value="psychological">Psychological - Autism Evaluation Service</option>
|
||||
<option value="sociological">Sociological - Learners Social Club Service</option>
|
||||
<option value="other_none">Other/None</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Insurance & Payment Options</span>
|
||||
<select name="payment_options" disabled={mode === 'off'}>
|
||||
<option value="" selected>Please select</option>
|
||||
<option>United Healthcare AHCCCS</option>
|
||||
<option>BCBS AZ</option>
|
||||
<option>United Healthcare</option>
|
||||
<option>Optum</option>
|
||||
<option>Tricare</option>
|
||||
<option>Care Credit</option>
|
||||
<option>Private Pay</option>
|
||||
<option value="Other">Other (please describe in comment)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>How did you hear about us?</span>
|
||||
<select name="referred_by" disabled={mode === 'off'}>
|
||||
<option value="" selected>Please select</option>
|
||||
<option>Facebook</option>
|
||||
<option>Google</option>
|
||||
<option>Primary Doctor</option>
|
||||
<option value="Specialist">Specialist (e.g., Developmental Psychologist)</option>
|
||||
<option>Client Referral</option>
|
||||
<option>Community Event</option>
|
||||
<option value="Other">Other (please describe in comment)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="service-inquiry-form__wide">
|
||||
<span>Additional Information/Comments</span>
|
||||
<textarea name="comment" rows="2" disabled={mode === 'off'}></textarea>
|
||||
</label>
|
||||
</div>
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.email}<span class="required-mark" aria-hidden="true">*</span></span>
|
||||
<input type="email" name="email" autocomplete="email" required disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.childFirstName}</span>
|
||||
<input name="child_first_name" autocomplete="off" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.childLastName}</span>
|
||||
<input name="child_last_name" autocomplete="off" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label class="service-inquiry-form__wide">
|
||||
<span>{copy.childBirthDate}</span>
|
||||
<input name="child_birth_date" inputmode="numeric" autocomplete="bday" placeholder="MM - DD - YYYY" disabled={mode === 'off'} />
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.location}</span>
|
||||
<select name="location_interest" disabled={mode === 'off'}>
|
||||
<option value="" selected>{copy.select}</option>
|
||||
<option value="aia_scottsdale">AIA Scottsdale</option>
|
||||
<option value="aia_glendale">AIA Glendale</option>
|
||||
<option value="other_none">Other/None</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.service}</span>
|
||||
<select name="service_interest" disabled={mode === 'off'}>
|
||||
<option value="" selected>{copy.select}</option>
|
||||
<option value="behavioral">Behavioral - ABA Therapy Service</option>
|
||||
<option value="psychological">Psychological - Autism Evaluation Service</option>
|
||||
<option value="sociological">Sociological - Learners Social Club Service</option>
|
||||
<option value="other_none">Other/None</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.payment}</span>
|
||||
<select name="payment_options" disabled={mode === 'off'}>
|
||||
<option value="" selected>{copy.select}</option>
|
||||
<option>United Healthcare AHCCCS</option>
|
||||
<option>BCBS AZ</option>
|
||||
<option>United Healthcare</option>
|
||||
<option>Optum</option>
|
||||
<option>Tricare</option>
|
||||
<option>Care Credit</option>
|
||||
<option>Private Pay</option>
|
||||
<option value="Other">Other (please describe in comment)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>{copy.referral}</span>
|
||||
<select name="referred_by" disabled={mode === 'off'}>
|
||||
<option value="" selected>{copy.select}</option>
|
||||
<option>Facebook</option>
|
||||
<option>Google</option>
|
||||
<option>Primary Doctor</option>
|
||||
<option value="Specialist">Specialist (e.g., Developmental Psychologist)</option>
|
||||
<option>Client Referral</option>
|
||||
<option>Community Event</option>
|
||||
<option value="Other">Other (please describe in comment)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="service-inquiry-form__wide">
|
||||
<span>{copy.comments}</span>
|
||||
<textarea name="comment" rows="2" disabled={mode === 'off'}></textarea>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="service-inquiry-form__footer">
|
||||
<p id={noteId} data-form-status>{mode === 'mock' ? 'Demo only: this local fixture never sends information.' : <>Online submission is not yet connected. Please call <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</>}</p>
|
||||
<button type="button" data-mock-submit disabled={mode === 'off'} aria-describedby={noteId}>Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-inquiry-form__footer">
|
||||
<p id={noteId} data-form-status>{mode === 'mock' ? copy.mock : <>{copy.disabled} <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</>}</p>
|
||||
<button type="button" data-mock-submit disabled={mode === 'off'} aria-describedby={noteId}>{copy.submit}</button>
|
||||
</div>
|
||||
</div>}
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
import { bindMockForms } from '../scripts/mock-form';
|
||||
bindMockForms();
|
||||
|
||||
const initializeServiceInquiryDrawers = () => {
|
||||
document.querySelectorAll('[data-service-inquiry-drawer]').forEach((element) => {
|
||||
if (!(element instanceof HTMLDialogElement) || element.dataset.initialized === 'true') return;
|
||||
|
||||
element.dataset.initialized = 'true';
|
||||
const explicitActivation = element.dataset.explicitActivation === 'true';
|
||||
const closeButton = element.querySelector('[data-service-inquiry-close]');
|
||||
const title = element.querySelector('[data-service-inquiry-title]');
|
||||
const frameAdapter = element.querySelector('[data-jotform-form-a]');
|
||||
const triggers = Array.from(document.querySelectorAll(`[data-service-inquiry-open][aria-controls="${element.id}"]`));
|
||||
const dismissKey = element.dataset.dismissKey;
|
||||
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||
let closeTimer: number | undefined;
|
||||
let trigger: HTMLElement | undefined;
|
||||
|
||||
const wasDismissed = () => {
|
||||
try {
|
||||
@@ -208,7 +318,7 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
|
||||
const closeDrawer = () => {
|
||||
if (!element.open) return;
|
||||
rememberDismissal();
|
||||
if (!explicitActivation) rememberDismissal();
|
||||
element.classList.remove('is-open');
|
||||
window.clearTimeout(closeTimer);
|
||||
|
||||
@@ -220,17 +330,23 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
closeTimer = window.setTimeout(finishClose, 500);
|
||||
};
|
||||
|
||||
const openDrawer = () => {
|
||||
if (element.open || wasDismissed()) return;
|
||||
const openDrawer = (openedBy?: EventTarget | null) => {
|
||||
if (element.open || (!explicitActivation && wasDismissed())) return;
|
||||
trigger = openedBy instanceof HTMLElement ? openedBy : undefined;
|
||||
element.showModal();
|
||||
document.documentElement.classList.add('service-inquiry-open');
|
||||
if (explicitActivation && frameAdapter instanceof HTMLElement) {
|
||||
frameAdapter.dispatchEvent(new Event('aia:jotform-activate'));
|
||||
}
|
||||
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||
element.classList.add('is-open');
|
||||
if (title instanceof HTMLElement) title.focus({ preventScroll: true });
|
||||
if (closeButton instanceof HTMLElement) closeButton.focus({ preventScroll: true });
|
||||
else if (title instanceof HTMLElement) title.focus({ preventScroll: true });
|
||||
}));
|
||||
};
|
||||
|
||||
closeButton?.addEventListener('click', closeDrawer);
|
||||
triggers.forEach((openButton) => openButton.addEventListener('click', () => openDrawer(openButton)));
|
||||
element.addEventListener('cancel', (event) => {
|
||||
event.preventDefault();
|
||||
closeDrawer();
|
||||
@@ -241,9 +357,13 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
element.addEventListener('close', () => {
|
||||
element.classList.remove('is-open');
|
||||
document.documentElement.classList.remove('service-inquiry-open');
|
||||
if (trigger instanceof HTMLElement) {
|
||||
trigger.focus({ preventScroll: true });
|
||||
trigger = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
window.setTimeout(openDrawer, 10_000);
|
||||
if (!explicitActivation) window.setTimeout(() => openDrawer(undefined), 10_000);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -255,6 +375,41 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__open {
|
||||
background: var(--color-accent, #ffbd59);
|
||||
border: 2px solid var(--color-accent, #ffbd59);
|
||||
border-radius: 4px;
|
||||
color: var(--color-primary);
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
margin: 1.5rem auto 0;
|
||||
padding: .75rem 1rem;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__open:hover,
|
||||
.service-inquiry-drawer__open:focus-visible {
|
||||
background: transparent;
|
||||
border-color: var(--color-accent-strong, #ff914d);
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__open:focus-visible {
|
||||
outline: 3px solid var(--color-focus, #115bbd);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__noscript {
|
||||
margin: 1.5rem auto 0;
|
||||
max-width: 42rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__noscript a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: .15em;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer {
|
||||
background: white;
|
||||
border: 0;
|
||||
@@ -271,7 +426,7 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
padding: 0;
|
||||
transform: translateX(calc(100% + 20px));
|
||||
transition: opacity 300ms ease, transform 500ms ease;
|
||||
width: 608px;
|
||||
width: min(760px, calc(100vw - 20px));
|
||||
}
|
||||
|
||||
.service-inquiry-drawer.is-open {
|
||||
@@ -301,11 +456,11 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__close:focus-visible {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline: 3px solid var(--color-focus, #115bbd);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@@ -317,18 +472,24 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
.service-inquiry-drawer__intro h2 {
|
||||
font-family: var(--font-body);
|
||||
font-size: 1.625rem;
|
||||
line-height: 1.05;
|
||||
line-height: 1.1;
|
||||
margin: 10px 0 16px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__intro p {
|
||||
line-height: 1.2;
|
||||
margin: 0 0 16px;
|
||||
line-height: 1.45;
|
||||
margin: 0 auto 16px;
|
||||
max-width: 42rem;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__intro p:last-child {
|
||||
margin-bottom: 0;
|
||||
.service-inquiry-drawer__privacy {
|
||||
color: var(--color-muted);
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__iframe {
|
||||
padding: 2rem 3.75rem 3.75rem;
|
||||
}
|
||||
|
||||
.service-inquiry-form {
|
||||
@@ -477,8 +638,21 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.service-inquiry-drawer__intro {
|
||||
padding-top: 20px;
|
||||
.service-inquiry-drawer {
|
||||
inset: 0;
|
||||
max-height: 100dvh;
|
||||
max-width: 100vw;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__intro,
|
||||
.service-inquiry-drawer__iframe,
|
||||
.service-inquiry-form {
|
||||
padding-inline: 1.25rem;
|
||||
}
|
||||
|
||||
.service-inquiry-drawer__iframe {
|
||||
padding-block: 1.5rem 2.5rem;
|
||||
}
|
||||
|
||||
.service-inquiry-form__grid {
|
||||
@@ -499,13 +673,6 @@ const mockResult = resolveMockFormResult(import.meta.env.PUBLIC_AIA_FORMS_MOCK_R
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.service-inquiry-drawer__intro,
|
||||
.service-inquiry-form {
|
||||
padding-inline: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.service-inquiry-drawer,
|
||||
.service-inquiry-drawer::backdrop {
|
||||
|
||||
@@ -26,6 +26,7 @@ const formAIframe = resolveFormAIframe({
|
||||
rawMode: import.meta.env.PUBLIC_AIA_FORMS_MODE,
|
||||
liveApproved: import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED,
|
||||
isolatedTestApproved: import.meta.env.PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED,
|
||||
consultationTestApproved: import.meta.env.PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED,
|
||||
productionApproved: import.meta.env.PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED,
|
||||
environmentRole: import.meta.env.PUBLIC_AIA_FORMS_ENVIRONMENT,
|
||||
allowIndexing: import.meta.env.PUBLIC_ALLOW_INDEXING,
|
||||
|
||||
@@ -6,6 +6,7 @@ const formAIframe = resolveFormAIframe({
|
||||
rawMode: import.meta.env.PUBLIC_AIA_FORMS_MODE,
|
||||
liveApproved: import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED,
|
||||
isolatedTestApproved: import.meta.env.PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED,
|
||||
consultationTestApproved: import.meta.env.PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED,
|
||||
productionApproved: import.meta.env.PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED,
|
||||
environmentRole: import.meta.env.PUBLIC_AIA_FORMS_ENVIRONMENT,
|
||||
allowIndexing: import.meta.env.PUBLIC_ALLOW_INDEXING,
|
||||
|
||||
@@ -19,6 +19,7 @@ const formAIframe = resolveFormAIframe({
|
||||
rawMode: import.meta.env.PUBLIC_AIA_FORMS_MODE,
|
||||
liveApproved: import.meta.env.PUBLIC_AIA_FORMS_LIVE_APPROVED,
|
||||
isolatedTestApproved: import.meta.env.PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED,
|
||||
consultationTestApproved: import.meta.env.PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED,
|
||||
productionApproved: import.meta.env.PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED,
|
||||
environmentRole: import.meta.env.PUBLIC_AIA_FORMS_ENVIRONMENT,
|
||||
allowIndexing: import.meta.env.PUBLIC_ALLOW_INDEXING,
|
||||
|
||||
Reference in new issue
Block a user