183 lines · 6.6 KB
import { useState } from "react";
import { addEmail, removeEmail, resendVerificationEmail, setPrimaryEmail } from "~/fns/account-security";
import type { getSecuritySettings } from "~/fns/account-security";
import { useAction } from "~/hooks/use-action";
import { Button } from "~/ui/Button";
import { TextField } from "~/ui/Field";
import { ErrorBanner } from "~/ui/Callout";
import { Badge } from "~/ui/Badge";
import { Panel } from "~/ui/Panel";

type AccountEmail = Awaited<ReturnType<typeof getSecuritySettings>>["emails"][number];

type Notice = { text: string; devMailUrl?: string | null };
type RowProps = { entry: AccountEmail; hasPassword: boolean; onNotice: (notice: Notice) => void };

function openDevMail(url: string | null) {
  if (url) window.open(url, "_blank", "noopener");
}

function EmailRow({ entry, hasPassword, onNotice }: RowProps) {
  const resend = useAction(resendVerificationEmail, { invalidate: false });
  const remove = useAction(removeEmail);
  const makePrimary = useAction(setPrimaryEmail);
  const [confirming, setConfirming] = useState<"primary" | "remove" | null>(null);
  const error = resend.error ?? remove.error ?? makePrimary.error;
  const canMakePrimary = !entry.primary && entry.verified;

  async function promote(password: string) {
    if (await makePrimary.run({ data: { email: entry.email, password } })) {
      setConfirming(null);
      onNotice({ text: `${entry.email} is now your primary address.` });
    }
  }

  async function drop(password: string) {
    if (await remove.run({ data: { email: entry.email, password } })) {
      setConfirming(null);
      onNotice({ text: `${entry.email} was removed.` });
    }
  }