承認ワークフローApprovalWorkflowExperimental

承認・審査の段階を進行、差戻し、却下、完了の状態と記録で扱うワークフローです。

プレビュー

  1. 申請受付
    対応中
  2. 書類審査
    未着手
  3. 資格判定
    未着手
  4. 決定
    未着手
  5. 支給
    未着手

状態とバリエーション

進行中

現在段階を進め、必要に応じて差戻しや却下の理由入力へ切り替えます。

  1. 申請受付
    対応中
  2. 書類審査
    未着手
  3. 資格判定
    未着手
  4. 決定
    未着手
  5. 支給
    未着手

ゲートで停止

要件が未完了の時は次へ進めるボタンを無効化し、理由を hover/focus tooltip で説明します。

  1. 申請受付
    完了
  2. 書類審査
    対応中
  3. 資格判定
    未着手
  4. 決定
    未着手
  5. 支給
    未着手
必要書類のチェックが未完了です

完了済み

status が approved になると、操作面ではなく完了ステータスとして表示します。

  1. 申請受付
    完了
  2. 書類審査
    完了
  3. 資格判定
    完了
  4. 決定
    完了
  5. 支給
    完了

完了

プロパティ

表は横にスクロールできます
プロパティ初期値説明
stagesWorkflowStage[]-承認・審査の段階を順番通りに渡します。
valueWorkflowValue-現在段階、全体ステータス、各段階の記録を持つ controlled state です。
onChange(next: WorkflowValue) => void-次へ進める、差戻し、却下、完了の各操作で呼ばれます。
canAdvancebooleantrue現在段階から次へ進められるかを制御します。false の時は advanceHint を tooltip でも表示します。
advanceHintReactNode-次へ進めない理由です。無効ボタンの tooltip と補助テキストに使います。
allowSendBack / allowRejectbooleantrue差戻しと却下の操作を表示するかどうかです。
labelsApprovalWorkflowLabels-操作ボタン、理由入力、完了/却下表示の文言を差し替えます。

使い方

import * as React from "react";
import {
  ApprovalWorkflow,
  Button,
  Checkbox,
  type WorkflowStage,
  type WorkflowValue,
} from "@gunjo/ui";

const stages: WorkflowStage[] = [
  { id: "intake", label: "申請受付" },
  { id: "docs", label: "書類審査" },
  { id: "eligibility", label: "資格判定" },
  { id: "decision", label: "決定" },
  { id: "pay", label: "支給" },
];

export function ScreeningWorkflow() {
  const [value, setValue] = React.useState<WorkflowValue>({
    currentStageId: "intake",
    status: "in-progress",
    records: {},
  });
  const [docsChecked, setDocsChecked] = React.useState(false);
  const canAdvance = value.currentStageId === "docs" ? docsChecked : true;

  return (
    <div className="flex w-full max-w-xl flex-col gap-3 rounded-lg border bg-card p-4">
      <ApprovalWorkflow
        stages={stages}
        value={value}
        onChange={setValue}
        actor="審査担当 田中"
        canAdvance={canAdvance}
        advanceHint="必要書類のチェックが未完了です"
        now={() => "2026/06/24 10:30"}
      />

      {value.currentStageId === "docs" && value.status === "in-progress" ? (
        <label className="flex items-center gap-2 rounded-md border bg-muted/30 px-3 py-2 text-sm">
          <Checkbox checked={docsChecked} onCheckedChange={(checked) => setDocsChecked(Boolean(checked))} />
          必要書類をすべて確認した
        </label>
      ) : null}

      {value.status !== "in-progress" ? (
        <Button
          type="button"
          size="sm"
          variant="ghost"
          className="self-start"
          onClick={() => {
            setValue({ currentStageId: "intake", status: "in-progress", records: {} });
            setDocsChecked(false);
          }}
        >
          リセット
        </Button>
      ) : null}
    </div>
  );
}

使用コンポーネント