hooks#useHubspotForm TypeScript Examples
The following examples show how to use
hooks#useHubspotForm.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
Header = ({ breadcrumbs = [] }) => {
const formEl = useRef(null);
const { user } = useApi();
const [form, setForm] = useState({
email: user?.email,
reaction: "",
feedback: "",
});
const [formSent, setFormSent] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
const { data, handleSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_FEEDBACK_FORM_ID,
});
useEffect(() => {
if (data) {
setFormSent(true);
formEl.current.reset();
}
}, [data]);
useEffect(() => {
if (user) {
setForm({ ...form, email: user.email });
}
}, [user]);
return (
<Box
css={{
width: "100%",
borderBottom: "1px solid",
borderColor: "$neutral6",
}}>
<Flex
align="center"
justify="between"
css={{
px: "$6",
height: 60,
width: "100%",
margin: "0 auto",
maxWidth: "1520px",
}}>
<Breadcrumbs aria-label="breadcrumb">
{breadcrumbs.map((breadcrumb, i) => {
if (breadcrumb?.href) {
return (
<Link key={i} href={breadcrumb.href} passHref>
<A variant="primary">{breadcrumb.title}</A>
</Link>
);
}
return <Text key={i}>{breadcrumb.title}</Text>;
})}
</Breadcrumbs>
<Flex align="center" css={{ fontSize: "$3" }}>
<Flex
align="center"
css={{
cursor: "pointer",
mr: "$5",
background: "transparent",
appearance: "none",
border: "none",
}}>
<StyledDocumentationIcon />
<Link href="/docs/guides" passHref>
<A
css={{
ml: "$2",
color: "$hiContrast",
textDecoration: "none",
"&:hover": {
textDecoration: "none",
},
}}>
<Box>Documentation</Box>
</A>
</Link>
</Flex>
<DropdownMenu>
<Flex
as={DropdownMenuTrigger}
align="center"
css={{
cursor: "pointer",
mr: "$5",
background: "transparent",
appearance: "none",
border: "none",
}}>
<StyledHornIcon />
<Box css={{ fontSize: "$3", color: "$hiContrast" }}>Feedback</Box>
</Flex>
<DropdownMenuContent
css={{
padding: "18px 20px 12px",
position: "relative",
width: "313px",
minHeight: "180px",
mt: "$4",
boxShadow:
"0px 5px 14px rgba(0, 0, 0, 0.22), 0px 0px 2px rgba(0, 0, 0, 0.2)",
background: "$panel",
display: "flex",
flexDirection: "column",
justifyContent: "center",
}}>
<Box css={{ position: "absolute", right: "12px", top: "-12px" }}>
<StyledPolygonIcon />
</Box>
{!formSent ? (
<>
<Text
size="2"
css={{
mb: "$3",
display: "flex",
ai: "center",
jc: "space-between",
}}>
Feedback
{errorMessage && (
<Text variant="red" size="2">
{errorMessage}
</Text>
)}
</Text>
<Box ref={formEl} as="form" onSubmit={handleSubmit}>
<TextArea
size="2"
required
name="feedback"
id="feedback"
placeholder="Your feedback"
css={{ px: "$2", width: "100%", boxSizing: "border-box" }}
onChange={(e) => {
const value = e.target.value;
setForm((prev) => ({ ...prev, feedback: value }));
}}
/>
<Flex align="center" justify="between" css={{ mt: "$3" }}>
<Flex>
{reactions.map((reaction, idx) => (
<Box
key={idx}
onClick={() => {
setErrorMessage("");
setForm((prev) => ({
...prev,
reaction: reaction,
}));
}}
css={{
width: "36px",
height: "36px",
borderRadius: "50%",
border:
reaction === form.reaction
? "1px solid $violet9"
: "1px solid $primary7",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: "20px",
marginRight: "$1",
cursor: "pointer",
":last-of-type": {
marginRight: "0px",
},
}}>
{reaction}
</Box>
))}
<input
name="emoji"
id="emoji"
onChange={(e) => {
const value = e.target.value;
setForm((prev) => ({ ...prev, reaction: value }));
}}
value={form.reaction}
style={{
visibility: "hidden",
width: "0px",
height: "0px",
}}
/>
<input name="email" type="hidden" value={form.email} />
</Flex>
<Button disabled={formSent} type="submit">
Send
</Button>
</Flex>
</Box>
</>
) : (
<Flex
align="center"
justify="center"
css={{ flexDirection: "column" }}>
<StyledCheckedIcon />
<Text css={{ textALign: "center", margin: "$3 0 $2" }}>
Your feedback has been received!
</Text>
<Text> Thank you for your help.</Text>
</Flex>
)}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<Box
as={DropdownMenuTrigger}
css={{
background: "transparent",
appearance: "none",
WebkitAppearance: "none",
border: "none",
p: 0,
}}>
<StyledQuestionMarkIcon />
</Box>
<DropdownMenuContent
css={{
padding: "18px 54px 18px 18px",
position: "relative",
mt: "$4",
boxShadow:
"0px 5px 14px rgba(0, 0, 0, 0.22), 0px 0px 2px rgba(0, 0, 0, 0.2)",
background: "$panel",
right: "-13px",
}}>
<Box css={{ position: "absolute", right: "6px", top: "-12px" }}>
<StyledPolygonIcon />
</Box>
<Text size="2" css={{ mb: "$3", color: "$primary9" }}>
HELP
</Text>
<Link href="/docs/guides" passHref>
<A
css={{
display: "flex",
alignItems: "center",
textDecoration: "none",
mb: "$3",
cursor: "pointer",
}}>
<StyledDocumentationIcon />
<Text css={{ margin: "0 $2" }}>Documentation</Text>
<StyledHyperlinkIcon />
</A>
</Link>
<Link href="/contact" passHref>
<A>
<Flex align="center" css={{ cursor: "pointer" }}>
<StyledSupportIcon />
<Text css={{ margin: "0 $2" }}>Contact Support</Text>
</Flex>
</A>
</Link>
</DropdownMenuContent>
</DropdownMenu>
</Flex>
</Flex>
</Box>
);
}
Example #2
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
PaymentMethodDialog = ({ invalidateQuery }) => {
const { user, updateCustomerPaymentMethod } = useApi();
const [status, setStatus] = useState("initial");
const stripe = useStripe();
const { register, handleSubmit } = useForm();
const elements = useElements();
const [open, setOpen] = useState(false);
const [openSnackbar] = useSnackbar();
const { resolvedTheme } = useTheme();
const { handleSubmit: hubspotSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_STRIPE_FORM_ID,
});
function createPaymentMethod({
cardElement,
stripeCustomerId,
billingDetails,
}) {
return stripe
.createPaymentMethod({
type: "card",
card: cardElement,
billing_details: billingDetails,
})
.then(async (result) => {
const paymentMethod = result.paymentMethod;
if (result.error) {
setStatus("error");
} else {
updateCustomerPaymentMethod({
stripeCustomerId,
stripeCustomerPaymentMethodId: paymentMethod.id,
})
// If the card is declined, display an error to the user.
.then((result: any) => {
if (result.error) {
setStatus("error");
// The card had an error when trying to attach it to a customer.
throw result;
}
return result;
})
.then(onPaymentChangeComplete)
.catch((error) => {
console.log(error);
setStatus("error");
});
}
});
}
async function onPaymentChangeComplete() {
setStatus("succeeded");
await invalidateQuery();
setOpen(false);
}
const onSubmit = async (data, e) => {
e.preventDefault();
hubspotSubmit(e);
// Abort if form isn't valid
if (!e.target.reportValidity()) return;
setStatus("processing");
const cardElement = elements!.getElement(CardElement);
createPaymentMethod({
cardElement,
stripeCustomerId: user.stripeCustomerId,
billingDetails: {
name: data.name,
email: data.email,
phone: data.phone,
address: {
line1: data.address,
city: data.city,
state: data.state,
postal_code: data.postalCode,
},
},
});
};
return (
<AlertDialog open={open} onOpenChange={() => setOpen(!open)}>
<Flex css={{ ai: "center" }}>
<Button
size="2"
variant="primary"
onClick={() => {
setOpen(true);
}}>
<MdCreditCard style={{ marginRight: "8px" }} />
{!user.stripeCustomerPaymentMethodId
? "Add Payment Method"
: "Change Payment Method"}
</Button>
</Flex>
<AlertDialogContent css={{ maxWidth: 450, px: "$5", pt: "$4", pb: "$4" }}>
<Box
as="form"
onSubmit={handleSubmit(onSubmit)}
id="billing-stripe-form">
<AlertDialogTitle asChild>
<Heading size="1">
{!user.stripeCustomerPaymentMethodId
? "Add payment method"
: "Change payment method"}
</Heading>
</AlertDialogTitle>
<AlertDialogDescription css={{ mt: "$4" }}>
<Box css={{ color: "$hiContrast" }}>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="name">
Full name
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="Jane Doe"
id="name"
name="name"
type="text"
css={{ width: "100%", mb: "$2" }}
required
/>
</Box>
<Grid
gap={2}
css={{
gridTemplateColumns: "1fr 1fr",
width: "100%",
alignItems: "center",
mb: "$2",
}}>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="email">
Email
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="[email protected]"
id="email"
css={{ width: "100%" }}
name="email"
type="email"
required
/>
</Box>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="phone">
Phone
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="(941) 555-0123"
id="phone"
css={{ width: "100%" }}
name="phone"
type="text"
required
/>
</Box>
</Grid>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="address">
Address
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="185 Berry St"
id="address"
name="address"
type="text"
css={{ width: "100%", mb: "$2" }}
required
/>
</Box>
<Grid
gap={2}
css={{
gridTemplateColumns: "1fr 1fr 1fr",
width: "100%",
alignItems: "center",
mb: "$2",
}}>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="city">
City
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="Brooklyn"
id="city"
css={{ width: "100%" }}
name="city"
type="text"
required
/>
</Box>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="State">
State
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="NY"
id="name"
css={{ width: "100%" }}
name="state"
type="text"
required
/>
</Box>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="postalCode">
ZIP
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="11211"
id="postalCode"
css={{ width: "100%" }}
name="postalCode"
type="text"
required
/>
</Box>
</Grid>
<Box
css={{
fontSize: "$1",
color: "$hiContrast",
fontWeight: 500,
mb: "$1",
}}>
Card
</Box>
<Box
css={{
border: "1px solid $colors$primary7",
borderRadius: 6,
background: "$loContrast",
px: "$2",
}}>
<CardElement
options={{
iconStyle: "solid",
style: {
base: {
backgroundColor:
resolvedTheme === "light" ? "white" : "#161618",
iconColor: "#5746af",
color: resolvedTheme === "light" ? "#161618" : "white",
fontWeight: "500",
fontFamily:
"Inter, Roboto, Open Sans, Segoe UI, sans-serif",
fontSize: "14px",
lineHeight: "36px",
fontSmoothing: "antialiased",
"::placeholder": {
color: "#687176",
},
":-webkit-autofill": {
color: "transparent",
},
},
invalid: {
iconColor: "red",
color: "red",
},
},
}}
onChange={(e) => {
if (e.error) {
setStatus("error");
}
}}
/>
</Box>
</Box>
</AlertDialogDescription>
<Flex css={{ jc: "flex-end", gap: "$3", mt: "$5" }}>
<AlertDialogCancel asChild>
<Button
size="2"
onClick={() => {
setOpen(false);
}}
ghost>
Cancel
</Button>
</AlertDialogCancel>
<Button
size="2"
className="elements-style-background"
type="submit"
disabled={
!["initial", "succeeded", "error"].includes(status) || !stripe
}
variant="primary">
{status === "processing" && (
<Spinner
css={{
color: "$hiContrast",
width: 16,
height: 16,
mr: "$2",
}}
/>
)}
Continue
</Button>
</Flex>
</Box>
</AlertDialogContent>
</AlertDialog>
);
}
Example #3
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
PlanForm = ({ stripeProductId, text, variant, disabled, onClick }) => {
const { user, updateSubscription } = useApi();
const [status, setStatus] = useState("initial");
const stripe = useStripe();
const elements = useElements();
const [open, setOpen] = useState(false);
const [openSnackbar] = useSnackbar();
const { register, handleSubmit } = useForm();
const { theme } = useTheme();
const { handleSubmit: hubspotSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_STRIPE_FORM_ID,
});
function createPaymentMethod({
cardElement,
stripeCustomerId,
stripeCustomerSubscriptionId,
stripeProductId,
billingDetails,
}) {
return stripe
.createPaymentMethod({
type: "card",
card: cardElement,
billing_details: billingDetails,
})
.then(async (result) => {
const paymentMethod = result.paymentMethod;
if (result.error) {
console.log(result.error);
setStatus("error");
} else {
updateSubscription({
stripeCustomerId,
stripeCustomerPaymentMethodId: paymentMethod.id,
stripeCustomerSubscriptionId,
stripeProductId,
})
// If the card is declined, display an error to the user.
.then((result: any) => {
if (result.error) {
setStatus("error");
console.log(result.error);
// The card had an error when trying to attach it to a customer.
throw result;
}
return result;
})
// Normalize the result to contain the object returned by Stripe.
// Add the additional details we need.
.then((result) => {
return {
paymentMethodId: paymentMethod.id,
subscription: result,
};
})
// Some payment methods require a customer to be on session
// to complete the payment process. Check the status of the
// payment intent to handle these actions.
.then(handlePaymentThatRequiresCustomerAction)
// No more actions required. Provision your service for the user.
.then(onSubscriptionComplete)
.catch((error) => {
console.log(error);
setStatus("error");
// An error has happened. Display the failure to the user here.
// We utilize the HTML element we created.
//showCardError(error);
});
}
});
}
async function onSubscriptionComplete() {
setStatus("succeeded");
setOpen(false);
}
function handlePaymentThatRequiresCustomerAction({
subscription,
invoice,
paymentMethodId,
}) {
let setupIntent = subscription.pending_setup_intent;
if (setupIntent && setupIntent.status === "requires_action") {
return stripe
.confirmCardSetup(setupIntent.client_secret, {
payment_method: paymentMethodId,
})
.then((result) => {
if (result.error) {
console.log(result.error);
setStatus("error");
// start code flow to handle updating the payment details
// Display error message in your UI.
// The card was declined (i.e. insufficient funds, card has expired, etc)
throw result;
} else {
if (result.setupIntent.status === "succeeded") {
// There's a risk of the customer closing the window before callback
// execution. To handle this case, set up a webhook endpoint and
// listen to setup_intent.succeeded.
return {
subscription: subscription,
invoice: invoice,
paymentMethodId: paymentMethodId,
};
}
}
});
} else {
// No customer action needed
return { subscription, paymentMethodId };
}
}
const onSubmit = async (data, e) => {
e.preventDefault();
hubspotSubmit(e);
// Abort if form isn't valid
if (!e.target.reportValidity()) return;
setStatus("processing");
// If user already submitted payment, don't ask for payment information again
if (user.stripeCustomerPaymentMethodId) {
await updateSubscription({
stripeCustomerId: user.stripeCustomerId,
stripeCustomerPaymentMethodId: user.stripeCustomerPaymentMethodId,
stripeCustomerSubscriptionId: user.stripeCustomerSubscriptionId,
stripeProductId,
});
setStatus("succeeded");
setOpen(false);
} else {
const cardElement = elements!.getElement(CardElement);
createPaymentMethod({
cardElement,
stripeCustomerId: user.stripeCustomerId,
stripeCustomerSubscriptionId: user.stripeCustomerSubscriptionId,
stripeProductId,
billingDetails: {
name: data.name,
email: data.email,
phone: data.phone,
address: {
line1: data.address,
city: data.city,
state: data.state,
postal_code: data.postalCode,
},
},
});
}
};
return (
<>
<AlertDialog open={open} onOpenChange={() => setOpen(!open)}>
<Flex css={{ ai: "center" }}>
<Button
size="3"
css={{ width: "100%" }}
disabled={disabled}
variant={variant}
onClick={() => {
onClick();
setOpen(true);
}}>
{text}
</Button>
</Flex>
<AlertDialogContent
css={{ maxWidth: 450, px: "$5", pt: "$4", pb: "$4" }}>
<Box
as="form"
onSubmit={handleSubmit(onSubmit)}
id="plan-stripe-form">
<AlertDialogTitle asChild>
<Heading size="1">
{!user.stripeCustomerPaymentMethodId
? "Enter card details"
: "Change plan"}
</Heading>
</AlertDialogTitle>
<AlertDialogDescription asChild>
{!user.stripeCustomerPaymentMethodId ? (
<Box
css={{ mt: "$4", lineHeight: "22px", color: "$hiContrast" }}>
<Box>
<Label css={{ mb: "$1", display: "block" }} htmlFor="name">
Full name
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="Jane Doe"
id="name"
name="name"
type="text"
css={{ width: "100%", mb: "$2" }}
required
/>
</Box>
<Grid
gap={2}
css={{
gridTemplateColumns: "1fr 1fr",
width: "100%",
alignItems: "center",
mb: "$2",
}}>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="email">
Email
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="[email protected]"
id="email"
css={{ width: "100%" }}
name="email"
type="email"
required
/>
</Box>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="phone">
Phone
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="(941) 555-0123"
id="phone"
css={{ width: "100%" }}
name="phone"
type="text"
required
/>
</Box>
</Grid>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="address">
Address
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="185 Berry St"
id="address"
name="address"
type="text"
css={{ width: "100%", mb: "$2" }}
required
/>
</Box>
<Grid
gap={2}
css={{
gridTemplateColumns: "1fr 1fr 1fr",
width: "100%",
alignItems: "center",
mb: "$2",
}}>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="city">
City
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="Brooklyn"
id="city"
css={{ width: "100%" }}
name="city"
type="text"
required
/>
</Box>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="State">
State
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="NY"
id="name"
css={{ width: "100%" }}
name="state"
type="text"
required
/>
</Box>
<Box>
<Label
css={{ mb: "$1", display: "block" }}
htmlFor="postalCode">
ZIP
</Label>
<TextField
size="2"
ref={register({ required: true })}
placeholder="11211"
id="postalCode"
css={{ width: "100%" }}
name="postalCode"
type="text"
required
/>
</Box>
</Grid>
<Box
css={{
fontSize: "$1",
color: "$hiContrast",
fontWeight: 500,
mb: "$1",
}}>
Card
</Box>
<Box
css={{
border: "1px solid $colors$primary7",
borderRadius: 6,
background: "$loContrast",
px: "$2",
}}>
<CardElement
options={{
iconStyle: "solid",
style: {
base: {
backgroundColor:
theme === "light" ? "white" : "#161618",
iconColor: "#5746af",
color: theme === "light" ? "#161618" : "white",
fontWeight: "500",
fontFamily:
"Inter, Roboto, Open Sans, Segoe UI, sans-serif",
fontSize: "14px",
lineHeight: "36px",
fontSmoothing: "antialiased",
"::placeholder": {
color: "#687176",
},
":-webkit-autofill": {
color: "transparent",
},
},
invalid: {
iconColor: "red",
color: "red",
},
},
}}
onChange={(e) => {
if (e.error) {
setStatus("error");
}
}}
/>
</Box>
</Box>
) : (
<Text variant="gray">
You are currently using the{" "}
{products[user.stripeProductId].name} plan. Do you want to{" "}
{products[stripeProductId].order <
products[user.stripeProductId].order
? "downgrade"
: "upgrade"}{" "}
to the {products[stripeProductId].name} plan?
</Text>
)}
</AlertDialogDescription>
<Flex css={{ jc: "flex-end", gap: "$3", mt: "$5" }}>
<AlertDialogCancel asChild>
<Button
size="2"
onClick={() => {
setOpen(false);
}}
ghost>
Cancel
</Button>
</AlertDialogCancel>
<Button
size="2"
className="elements-style-background"
type="submit"
disabled={
!["initial", "succeeded", "error"].includes(status) || !stripe
}
variant="primary">
{status === "processing" && (
<Spinner
css={{
width: 16,
height: 16,
mr: "$2",
}}
/>
)}
Continue
</Button>
</Flex>
</Box>
</AlertDialogContent>
</AlertDialog>
</>
);
}
Example #4
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
Contact = () => {
const formEl = useRef(null);
const { data, handleSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_FORM_ID,
});
const [submitted, setSubmitted] = useState(false);
useEffect(() => {
if (data) {
setSubmitted(true);
formEl.current.reset();
let timer = setTimeout(() => {
setSubmitted(false);
}, 4500);
return () => {
clearTimeout(timer);
};
}
}, [data]);
return (
<Box css={{ position: "relative" }}>
<Guides backgroundColor="$panel" />
<Container
size="3"
css={{ py: 88, px: 0, width: "100%", position: "relative" }}>
<Box
css={{
px: "$6",
"@bp2": {
px: "$3",
},
}}>
<Box css={{ mb: 48, textAlign: "center" }}>
<Heading
size="3"
as="h2"
css={{
fontWeight: 700,
color: "$hiContrast",
fontSize: "$8",
mb: "$5",
}}>
Get in touch
</Heading>
<Text
size="4"
variant="gray"
css={{ maxWidth: 512, margin: "0 auto" }}>
Learn more about Livepeer Video Service's streaming API and media
server. Leave us a message and we’ll get back to you.
<br />
<br />
Or email us at{" "}
<A
href="mailto:[email protected]?subject=Livepeer%20Video%20Services%20inquiry"
target="_blank">
[email protected]
</A>
.
</Text>
</Box>
<Box
as="form"
ref={formEl}
onSubmit={handleSubmit}
css={{ maxWidth: 700, margin: "0 auto", textAlign: "center" }}>
<Grid
css={{
mb: "$4",
justifyContent: "center",
alignItems: "center",
gridTemplateColumns: "repeat(1,1fr)",
"@bp2": {
gridTemplateColumns: "repeat(2,1fr)",
},
}}
gap="5">
<TextField
size="3"
id="firstname"
name="firstname"
type="text"
placeholder="First Name"
/>
<TextField
size="3"
id="lastname"
name="lastname"
type="text"
placeholder="Last Name"
/>
</Grid>
<Grid
css={{
mb: "$4",
justifyContent: "center",
alignItems: "center",
gridTemplateColumns: "repeat(1,1fr)",
"@bp2": {
gridTemplateColumns: "repeat(2,1fr)",
},
}}
gap="5">
<TextField
size="3"
id="email"
name="email"
type="email"
placeholder="Email*"
required
/>
<TextField
size="3"
id="company"
name="company"
type="text"
placeholder="Organization"
/>
</Grid>
<TextArea
size="3"
id="message"
css={{ width: "100%", boxSizing: "border-box" }}
name="message"
placeholder="Message*"
required
/>
<Box css={{ textAlign: "center" }}>
<Button arrow css={{ mx: "auto", mt: "$4", px: "$4" }}>
Submit
</Button>
<Fade in={submitted}>
<Text variant="gray" css={{ mt: "$3" }}>
Thank you for getting in touch. Our team will get back to you
soon.
</Text>
</Fade>
</Box>
</Box>
</Box>
</Container>
</Box>
);
}
Example #5
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
Login = ({
id,
showName = false,
showOrganization = false,
showPhone = false,
showEmail,
showPassword,
buttonText,
onSubmit,
loading,
errors,
}) => {
const router = useRouter();
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [organization, setOrganization] = useState("");
const [phone, setPhone] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const { handleSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_LOGIN_FORM_ID,
});
useEffect(() => {
if (router?.query?.email) {
setEmail(router.query.email as string);
}
}, [router?.query?.email]);
const submit = async (e) => {
e.preventDefault();
handleSubmit(e);
if (!showPassword) {
return onSubmit({ email });
}
const [hashedPassword] = await hash(password, FRONTEND_SALT);
// hash password, then
onSubmit({
email,
password: hashedPassword,
firstName,
lastName,
organization,
phone,
});
};
return (
<Box
css={{
position: "relative",
width: "100%",
}}>
<Box
as="form"
onSubmit={submit}
css={{
textAlign: "center",
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
mb: "$3",
ml: "auto",
mr: "auto",
maxWidth: 500,
}}
id={id}>
{showName && (
<Grid
gap={3}
css={{
gridTemplateColumns: "1fr 1fr",
width: "100%",
alignItems: "center",
}}>
<TextField
size="3"
id="firstName"
css={{ width: "100%", mb: "$3" }}
name="firstName"
type="text"
placeholder="First name"
required
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<TextField
size="3"
id="lastName"
css={{ width: "100%", mb: "$3" }}
name="lastName"
type="text"
placeholder="Last name"
required
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</Grid>
)}
{showOrganization && showPhone && (
<Grid
gap={3}
css={{
gridTemplateColumns: "1fr 1fr",
width: "100%",
alignItems: "center",
}}>
<TextField
size="3"
id="organization"
css={{ width: "100%", mb: "$3" }}
name="organization"
type="organization"
placeholder="Organization (optional)"
value={organization}
onChange={(e) => setOrganization(e.target.value)}
/>
<TextField
size="3"
id="phone"
css={{ width: "100%", mb: "$3" }}
name="phone"
type="phone"
placeholder="Phone (optional)"
value={phone}
onChange={(e) => setPhone(e.target.value)}
/>
</Grid>
)}
{showEmail && (
<TextField
size="3"
id="email"
css={{
width: "100%",
mb: "$3",
mx: "$2",
"@bp1": {
mx: "$4",
},
}}
name="email"
type="email"
placeholder="Email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
)}
{showPassword && (
<TextField
size="3"
id="password"
css={{
width: "100%",
mx: "$2",
"@bp1": {
mx: "$4",
},
}}
name="password"
type="password"
placeholder="Password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
)}
<Box>{errors.join(", ")} </Box>
<Button css={{ mt: "$2", px: "$5" }}>
{loading ? "Loading..." : buttonText}
</Button>
</Box>
</Box>
);
}
Example #6
Source File: contact.tsx From livepeer-com with MIT License | 4 votes |
ContactPage = () => {
const router = useRouter();
const { query } = router;
const formEl = useRef(null);
const { data, handleSubmit } = useHubspotForm({
portalId: process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID,
formId: process.env.NEXT_PUBLIC_HUBSPOT_CONTACT_FORM_ID,
});
const [submitted, setSubmitted] = useState(false);
useEffect(() => {
if (data) {
setSubmitted(true);
formEl.current.reset();
router.push("/contact?submitted=true");
let timer = setTimeout(() => {
setSubmitted(false);
}, 4500);
return () => {
clearTimeout(timer);
};
}
}, [data]);
return (
<Layout {...Content.metaData}>
<Guides backgroundColor="$neutral2" />
<Box css={{ position: "relative" }}>
<Container
size="3"
css={{
px: "$6",
py: "$7",
width: "100%",
"@bp3": {
py: "$8",
px: "$4",
},
}}>
<Box css={{ mb: "$5", textAlign: "center" }}>
<Heading as="h1" size="3" css={{ fontWeight: 600, mb: "$3" }}>
Get in touch
</Heading>
<Text size="4" variant="gray" css={{ maxWidth: 630, mx: "auto" }}>
Learn more about Livepeer Video Service's streaming API and media
server. Leave us a message and we’ll get back to you.
<br />
<br />
Or email us at{" "}
<A
href="mailto:[email protected]?subject=Livepeer%20Video%20Services%20inquiry"
target="_blank">
[email protected]
</A>
.
</Text>
</Box>
<Box
as="form"
id="contact-form"
ref={formEl}
onSubmit={handleSubmit}
css={{ maxWidth: 630, mx: "auto", textAlign: "center" }}>
<Grid
css={{
mb: "$4",
justifyContent: "center",
alignItems: "center",
gridTemplateColumns: "repeat(1,1fr)",
"@bp2": {
gridTemplateColumns: "repeat(2,1fr)",
},
}}
gap="5">
<TextField
size="3"
id="firstname"
name="firstname"
type="text"
placeholder="First Name*"
required
css={{ py: "$4" }}
/>
<TextField
size="3"
id="lastname"
name="lastname"
required
type="text"
placeholder="Last Name*"
/>
</Grid>
<TextField
css={{ width: "100%", boxSizing: "border-box", mb: "$4" }}
size="3"
id="email"
name="email"
type="email"
placeholder="Email*"
required
/>
<input name="utm_source" type="hidden" value={query?.utm_source} />
<input name="utm_medium" type="hidden" value={query?.utm_medium} />
<input
name="utm_campaign"
type="hidden"
value={query?.utm_campaign}
/>
<TextArea
size="3"
id="message"
css={{ width: "100%", boxSizing: "border-box", mb: "$4" }}
name="TICKET.content"
placeholder="How can we help you? To guide the discussion, please give us specific details on
your interest in speaking with our team. The more information, the better.*"
required
/>
<Box css={{ textAlign: "center" }}>
<Button arrow css={{ mx: "auto", mt: "$4", px: "$4" }}>
Submit
</Button>
<Fade in={submitted}>
<Text variant="gray" css={{ mt: "$3" }}>
Thank you for getting in touch. Our team will get back to you
soon.
</Text>
</Fade>
</Box>
</Box>
</Container>
</Box>
<Fade key={0}>
<Prefooter />
</Fade>
</Layout>
);
}