91 lines · 3.5 KB
import { useState } from "react";
import { adminDisable, adminEnable } from "~/fns/admin";
import type { getAdminOverview } from "~/fns/admin";
import { useAction } from "~/hooks/use-action";
import { Button } from "~/ui/Button";
import { ErrorBanner } from "~/ui/Callout";
import { EmptyState } from "~/ui/EmptyState";
import { Panel } from "~/ui/Panel";
import { RelativeTime } from "~/ui/RelativeTime";
import { TextLink } from "~/ui/TextLink";

type Accounts = Awaited<ReturnType<typeof getAdminOverview>>["disabledAccounts"];

const REASON_LABELS: Record<string, string> = { payment_dispute: "payment dispute", admin: "admin" };
const INPUT = "rounded-md border border-kumo-line bg-kumo-base px-2 py-1 text-kumo-strong";

/** Disabled accounts with their reason, plus disable (with a note) and re-enable. */
export function DisabledAccounts({ accounts }: { accounts: Accounts }) {
  const [name, setName] = useState("");
  const [note, setNote] = useState("");
  const disable = useAction(adminDisable);
  const enable = useAction(adminEnable);
  return (
    <Panel title="Disabled accounts">
      <div className="space-y-3 p-4 text-sm">
        <ErrorBanner message={disable.error ?? enable.error} />
        <form
          className="flex flex-wrap items-center gap-2"
          onSubmit={async (event) => {
            event.preventDefault();
            const target = name.trim();
            if (!target || !window.confirm(`Disable ${target}? Sign-in, tokens, billing and hosting all stop.`)) return;
            await disable.run({ data: { name: target, note: note.trim() || null } });
            setName("");
            setNote("");
          }}
        >
          <input
            aria-label="Account name"
            className={INPUT}