68 lines · 2.3 KB
import { mergeStack, restackPullRequest } from "~/fns/stacks";
import { useAction } from "~/hooks/use-action";
import { Button } from "~/ui/Button";
import { Callout, ErrorBanner } from "~/ui/Callout";
import { Code } from "~/ui/Code";
import type { usePull } from "~/hooks/use-pull";
import type { MergeMethod } from "~/lib/types";

type PullData = ReturnType<typeof usePull>;

/**
 * Merge box controls for a pull request stacked on another one: it can't merge into its parent's branch
 * from here, so it offers restacking onto the parent and merging the whole stack up to this point.
 */
export function StackMergeControls({
  owner,
  repo,
  data,
  method,
}: {
  owner: string;
  repo: string;
  data: PullData;
  method: MergeMethod;
}) {
  const restack = useAction(restackPullRequest);
  const merge = useAction(mergeStack);
  const { pull, stackedOn, stack } = data;
  if (!stackedOn) return null;
  const below = stack.filter((entry) => !entry.merged && entry.state === "open");
  const count = below.findIndex((entry) => entry.current) + 1;
  const trunk = stack[0]?.baseRef ?? pull.baseRef;
  return (
    <div className="space-y-3">
      <Callout tone="accent">
        Stacked on #{stackedOn.number}. When the pull requests below merge, this one is retargeted to{" "}
        <Code>{trunk}</Code> and restacked automatically.
      </Callout>
      <ErrorBanner message={restack.error ?? merge.error} />
      <div className="flex flex-wrap gap-2">