54 lines · 1.9 KB
import { useState } from "react";
import { addComment, setIssueOpenState } from "~/fns/issues";
import { useAction } from "~/hooks/use-action";
import { MarkdownEditor } from "./MarkdownEditor";
import { Button } from "~/ui/Button";
import { ErrorBanner } from "~/ui/Callout";
import { VerifyEmailHint } from "./VerifyEmailHint";
import { useEmailUnverified } from "~/hooks/use-viewer";

type Props = {
  owner: string;
  repo: string;
  number: number;
  state: "open" | "closed";
  canToggle: boolean;
  merged?: boolean;
};

export function CommentComposer({ owner, repo, number, state, canToggle, merged = false }: Props) {
  const [body, setBody] = useState("");
  const comment = useAction(addComment);
  const toggle = useAction(setIssueOpenState);
  const unverified = useEmailUnverified();
  if (unverified) return <VerifyEmailHint action="comment" className="text-sm" />;

  async function submit() {
    if (await comment.run({ data: { owner, repo, number, body, closeAfter: false } })) setBody("");
  }

  return (
    <div className="space-y-2">
      <ErrorBanner message={comment.error ?? toggle.error} />
      <MarkdownEditor value={body} onChange={setBody} owner={owner} repo={repo} />
      <div className="flex justify-end gap-2">
        {canToggle && !merged && (
          <Button
            pending={toggle.pending}
            onClick={async () => {
              if (body.trim()) await comment.run({ data: { owner, repo, number, body, closeAfter: false } });
              await toggle.run({ data: { owner, repo, number, state: state === "open" ? "closed" : "open" } });