255 lines · 10.6 KB
import { useEffect } from "react";
import type { getBilling } from "~/fns/billing";
import { openBillingPortal, startDomainAddonCheckout, startProCheckout, startTopupCheckout } from "~/fns/billing";
import { useAction } from "~/hooks/use-action";
import { formatQuantity, meterDef } from "~/lib/meters";
import { CREDIT_POOLS, CUSTOM_DOMAIN_LIMIT } from "~/lib/pricing";
import type { CreditPoolId } from "~/lib/pricing";
import { usd } from "~/lib/pricing-display";
import { trackEvent } from "~/lib/analytics";
import { Badge } from "~/ui/Badge";
import { Button } from "~/ui/Button";
import { ErrorBanner } from "~/ui/Callout";
import { Panel } from "~/ui/Panel";
import { RelativeTime } from "~/ui/RelativeTime";
import { ComputeRatesNote } from "./ComputeRatesNote";
import { InfoTip } from "./InfoTip";
import { VerifyEmailHint } from "~/components/VerifyEmailHint";
import { useEmailUnverified } from "~/hooks/use-viewer";

type Billing = Awaited<ReturnType<typeof getBilling>>;
type Action = { reset: () => void };

function go(result: { url: string } | undefined, kind: string) {
  if (!result?.url) return;
  trackEvent("checkout_started", { kind });
  window.location.assign(result.url);
}

/**
 * Coming back from Stripe with the browser's back button can restore this page from the back-forward cache with
 * its buttons still pending; clear them so the page is usable again.
 */
function useResetOnRestore(...actions: Action[]) {
  useEffect(() => {
    const onShow = (event: PageTransitionEvent) => {
      if (event.persisted) for (const action of actions) action.reset();
    };
    window.addEventListener("pageshow", onShow);
    return () => window.removeEventListener("pageshow", onShow);
  });