承認ワークフローApprovalWorkflowExperimental
承認・審査の段階を進行、差戻し、却下、完了の状態と記録で扱うワークフローです。
プレビュー
- 申請受付対応中
- 書類審査未着手
- 資格判定未着手
- 決定未着手
- 支給未着手
状態とバリエーション
進行中
現在段階を進め、必要に応じて差戻しや却下の理由入力へ切り替えます。
- 申請受付対応中
- 書類審査未着手
- 資格判定未着手
- 決定未着手
- 支給未着手
ゲートで停止
要件が未完了の時は次へ進めるボタンを無効化し、理由を hover/focus tooltip で説明します。
- 申請受付完了
- 書類審査対応中
- 資格判定未着手
- 決定未着手
- 支給未着手
必要書類のチェックが未完了です
完了済み
status が approved になると、操作面ではなく完了ステータスとして表示します。
- 申請受付完了
- 書類審査完了
- 資格判定完了
- 決定完了
- 支給完了
完了
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| stages | WorkflowStage[] | - | 承認・審査の段階を順番通りに渡します。 |
| value | WorkflowValue | - | 現在段階、全体ステータス、各段階の記録を持つ controlled state です。 |
| onChange | (next: WorkflowValue) => void | - | 次へ進める、差戻し、却下、完了の各操作で呼ばれます。 |
| canAdvance | boolean | true | 現在段階から次へ進められるかを制御します。false の時は advanceHint を tooltip でも表示します。 |
| advanceHint | ReactNode | - | 次へ進めない理由です。無効ボタンの tooltip と補助テキストに使います。 |
| allowSendBack / allowReject | boolean | true | 差戻しと却下の操作を表示するかどうかです。 |
| labels | ApprovalWorkflowLabels | - | 操作ボタン、理由入力、完了/却下表示の文言を差し替えます。 |
使い方
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>
);
}