50 lines · 1.9 KB
import { useState } from "react";
import { joinSignupWaitlist } from "~/fns/waitlist";
import { useAction } from "~/hooks/use-action";
import { useTurnstile } from "~/hooks/use-turnstile";
import { WAITLIST_INVITE_HOURS } from "~/lib/waitlist";
import { Button } from "~/ui/Button";
import { Callout, ErrorBanner } from "~/ui/Callout";
import { TextField } from "~/ui/Field";
import { TextLink } from "~/ui/TextLink";

/** Shown in place of the signup form while every seat under the admin's cap is taken. */
export function WaitlistForm({ turnstileSiteKey }: { turnstileSiteKey: string | null }) {
  const action = useAction(joinSignupWaitlist);
  const turnstile = useTurnstile(turnstileSiteKey, "signup");
  const [place, setPlace] = useState<number | null>(null);

  if (place !== null) {
    return (
      <Callout tone="success" as="output">
        You're on the list at number {place}. When a spot opens we'll email you a link to create your account. The link
        holds your spot for {WAITLIST_INVITE_HOURS} hours.
      </Callout>
    );
  }

  async function submit(event: React.SubmitEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = new FormData(event.currentTarget);
    const result = await action.run({
      data: { email: String(form.get("email") ?? ""), turnstileToken: turnstile.token },
    });
    if (result) setPlace(result.place);
    else turnstile.reset();
  }

  return (
    <form method="post" onSubmit={submit} className="space-y-4">
      <ErrorBanner message={action.error} />
      <TextField label="Email" name="email" type="email" autoComplete="email" required />
      {turnstile.widget}