You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
portainer/app/react/components/HubspotForm.tsx

113 lines
2.1 KiB

import { ReactNode, useRef } from 'react';
import { useQuery } from 'react-query';
let globalId = 0;
interface Props {
portalId: HubSpotCreateFormOptions['portalId'];
formId: HubSpotCreateFormOptions['formId'];
region: HubSpotCreateFormOptions['region'];
onSubmitted: () => void;
loading?: ReactNode;
}
export function HubspotForm({
loading,
portalId,
region,
formId,
onSubmitted,
}: Props) {
const elRef = useRef<HTMLDivElement>(null);
const id = useRef(`reactHubspotForm${globalId++}`);
const { isLoading } = useHubspotForm({
elId: id.current,
formId,
portalId,
region,
onSubmitted,
});
return (
<>
<div
ref={elRef}
id={id.current}
style={{ display: isLoading ? 'none' : 'block' }}
/>
{isLoading && loading}
</>
);
}
function useHubspotForm({
elId,
formId,
portalId,
region,
onSubmitted,
}: {
elId: string;
portalId: HubSpotCreateFormOptions['portalId'];
formId: HubSpotCreateFormOptions['formId'];
region: HubSpotCreateFormOptions['region'];
onSubmitted: () => void;
}) {
return useQuery(
['hubspot', { elId, formId, portalId, region }],
async () => {
await loadHubspot();
await createForm(`#${elId}`, {
formId,
portalId,
region,
onFormSubmit: onSubmitted,
});
},
{
refetchOnWindowFocus: false,
}
);
}
async function loadHubspot() {
return new Promise<void>((resolve) => {
if (window.hbspt) {
resolve();
return;
}
const script = document.createElement(`script`);
script.defer = true;
script.onload = () => {
resolve();
};
script.src = `//js.hsforms.net/forms/v2.js`;
document.head.appendChild(script);
});
}
async function createForm(
target: string,
options: Omit<HubSpotCreateFormOptions, 'target'>
) {
return new Promise<void>((resolve) => {
if (!window.hbspt) {
throw new Error('hbspt object is missing');
}
window.hbspt.forms.create({
...options,
target,
onFormReady(...rest) {
options.onFormReady?.(...rest);
resolve();
},
});
});
}