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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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(", ")}&nbsp;</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 vote down vote up
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>
  );
}