# 画面設計書 105-保留中FAQ一覧

## 概要

Captain AIが会話から自動生成した保留中のFAQ回答を管理するための一覧画面設計書です。承認待ちのFAQの確認、承認、編集、削除、一括操作を提供します。

### 本画面の処理概要

**業務上の目的・背景**：Captain AIは解決済み会話から自動的にFAQを生成する機能を持っています。自動生成されたFAQは「保留中（pending）」ステータスで作成され、管理者の承認を経て正式なナレッジベースに追加されます。この画面は品質管理プロセスの重要な部分を担い、AIが生成したコンテンツの精度と適切性を人間が確認します。

**画面へのアクセス方法**：FAQ一覧画面の保留中バナーの「Review」ボタン、またはURLに直接アクセスします。URLパスは `/app/accounts/:accountId/captain/:assistantId/faqs/pending` です。

**主要な操作・処理内容**：
1. 保留中FAQ一覧の表示（ページネーション対応）
2. FAQ検索（デバウンス処理付き）
3. FAQの承認（単体・一括）
4. FAQの編集
5. FAQの削除（単体・一括）
6. 一括選択と一括操作（承認/削除）
7. FAQ一覧画面への戻りナビゲーション

**画面遷移**：
- 遷移元：FAQ一覧画面（保留中バナー）
- 遷移先：FAQ一覧画面（戻るボタン）、会話詳細画面（関連会話リンク）

**権限による表示制御**：administrator および agent ロールがアクセス可能です。CAPTAINフィーチャーフラグが有効で、CloudまたはEnterpriseインストールタイプの場合のみ利用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 93 | アシスタントレスポンス | 主機能 | 保留中FAQ回答の一覧表示、承認、CRUD操作 |

## 画面種別

一覧 / 編集（ダイアログ）

## URL/ルーティング

| パス | ルート名 |
|------|----------|
| `/app/accounts/:accountId/captain/:assistantId/faqs/pending` | `captain_assistants_responses_pending` |

## 入出力項目

### 検索・フィルタ入力

| 項目名 | 物理名 | 型 | 必須 | バリデーション | 備考 |
|--------|--------|-----|------|---------------|------|
| 検索クエリ | searchQuery | string | No | - | 500msデバウンス |
| ページ番号 | page | number | No | - | デフォルト1 |

### 出力項目（一覧）

| 項目名 | 物理名 | 型 | 備考 |
|--------|--------|-----|------|
| FAQ ID | id | number | 内部識別子 |
| 質問 | question | string | FAQ質問文 |
| 回答 | answer | string | FAQ回答文 |
| アシスタント | assistant | object | 関連アシスタント情報 |
| 関連ドキュメント | documentable | object | 元会話情報 |
| ステータス | status | string | pending |
| 作成日時 | created_at | datetime | 作成日時 |
| 更新日時 | updated_at | datetime | 更新日時 |

## 表示項目

### ヘッダー領域

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 戻るボタン | アイコンボタン | FAQ一覧へ戻る |
| タイトル | "Pending FAQs" | ヘッダータイトル |

### 検索・フィルタ領域

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 検索入力フィールド | テキスト入力 | プレースホルダー付き |
| 一括選択バー | セレクションバー | 選択時のみ表示 |
| 一括承認ボタン | ゴーストボタン | 選択時のみ表示 |

### バナー表示

| 項目名 | 表示形式 | 条件 | 備考 |
|--------|----------|------|------|
| 制限バナー | LimitBanner | 80%超過時 | 使用量警告 |

### FAQカード

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 質問 | テキスト（太字） | カードタイトル |
| 回答 | テキスト | カード本文 |
| アシスタント情報 | バッジ | 関連アシスタント |
| 関連会話 | リンク | クリックで会話詳細へ |
| 作成/更新日時 | 相対日時 | フォーマット済み |
| アクションボタン群 | ボタン群 | 承認/編集/削除 |
| 選択チェックボックス | チェックボックス | ホバー時または選択モード時表示 |

### ページネーション

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 現在ページ | テキスト | ページ番号表示 |
| 総件数 | テキスト | 総レコード数 |
| ページ送りボタン | ボタン群 | 前後ナビゲーション |

## イベント仕様

### 1-FAQ承認（単体）

1. FAQカードの「Approve」ボタンをクリック
2. `handleAction({action: 'approve', id})` が呼び出される
3. `handleAccept()` が呼び出される
4. `captainResponses/update` アクションで status を 'approved' に更新
5. API成功時：成功メッセージ表示
6. API失敗時：エラーメッセージ表示

### 2-一括承認

1. FAQカードのチェックボックスで複数選択
2. BulkSelectBarの「Approve」ボタンをクリック
3. `handleBulkApprove()` が呼び出される
4. `captainBulkActions/handleBulkApprove` アクションが dispatch される
5. API成功時：成功メッセージ表示、一覧更新
6. API失敗時：エラーメッセージ表示

### 3-FAQ編集

1. FAQカードの「Edit」ボタンをクリック
2. `handleAction({action: 'edit', id})` が呼び出される
3. `CreateResponseDialog` が編集モードで表示される
4. 編集後、保存時に `captainResponses/update` アクションが dispatch される

### 4-FAQ削除（単体）

1. FAQカードの「Delete」ボタンをクリック
2. `handleAction({action: 'delete', id})` が呼び出される
3. `DeleteDialog` が表示される
4. 確認後、`captainResponses/delete` アクションが dispatch される

### 5-一括削除

1. FAQカードのチェックボックスで複数選択
2. BulkSelectBarの「Delete」ボタンをクリック
3. `BulkDeleteDialog` が表示される
4. 確認後、一括削除処理実行
5. `fetchResponseAfterBulkAction()` で一覧更新

### 6-検索

1. 検索フィールドに入力
2. 500msのデバウンス後、`debouncedSearch()` が実行
3. `fetchResponses(1)` でページ1から再取得

### 7-フィルタクリア

1. 空状態の「Clear filters」ボタンをクリック
2. `clearFilters()` が呼び出される
3. 検索クエリをクリアして再取得

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| FAQ一覧取得 | captain_assistant_responses | SELECT | 保留中FAQ取得 |
| FAQ承認 | captain_assistant_responses | UPDATE | ステータスをapprovedに更新 |
| FAQ編集 | captain_assistant_responses | UPDATE | FAQ内容更新 |
| FAQ削除 | captain_assistant_responses | DELETE | FAQ削除 |
| 一括承認 | captain_assistant_responses | UPDATE | 複数FAQのステータス更新 |

### テーブル別更新項目詳細

#### captain_assistant_responses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | `status = 'pending' AND assistant_id = :assistantId` | 一覧取得条件 |
| UPDATE | status | 'approved' | 承認処理 |
| UPDATE | question, answer | フォーム入力値 | 編集対象項目 |
| DELETE | - | `id = :responseId` | 指定ID削除 |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 |
|------|---------------|---------------|
| 成功 | CAPTAIN.RESPONSES.EDIT.APPROVE_SUCCESS_MESSAGE | FAQ承認成功 |
| エラー | CAPTAIN.RESPONSES.EDIT.ERROR_MESSAGE | FAQ操作失敗 |
| 成功 | CAPTAIN.RESPONSES.BULK_APPROVE.SUCCESS_MESSAGE | 一括承認成功 |
| エラー | CAPTAIN.RESPONSES.BULK_APPROVE.ERROR_MESSAGE | 一括承認失敗 |

## 例外処理

| 例外条件 | 処理内容 | 表示 |
|----------|----------|------|
| データ取得中 | isFetchingフラグでローディング表示 | Spinner |
| FAQ0件 | 空状態表示 | ResponsePageEmptyState (variant="pending") |
| 検索結果0件でフィルタあり | Clear filtersボタン表示 | フィルタクリアオプション |
| API通信エラー | アラート表示 | エラーメッセージ |
| 最後の1件削除後 | 前のページに遷移 | 自動ページ調整 |
| Captain未有効 | Paywallコンポーネント表示 | アップグレード案内 |

## 備考

- 保留中FAQはAIが会話から自動生成したもの
- filteredResponsesでフロントエンドでも追加フィルタリング（承認済みを除外）
- 一括承認は選択されたFAQを全て一度に承認
- showActions=trueでカードに承認/編集/削除ボタンを表示
- showMenu=falseでドロップダウンメニューを非表示（直接アクションボタン使用）

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、FAQデータの構造とステータス管理を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | response.js (store) | `app/javascript/dashboard/store/captain/response.js` | updateBulkResponsesメソッドを確認 |
| 1-2 | bulkActions.js | `app/javascript/dashboard/store/captain/bulkActions.js` | handleBulkApproveアクションを確認 |

**読解のコツ**: 一括承認は `captainBulkActions/handleBulkApprove` で処理され、成功後に `captainResponses/updateBulkResponses` でストア更新されます。

#### Step 2: エントリーポイントを理解する

処理の起点となるVueコンポーネントを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Pending.vue | `app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue` | メインコンポーネントの構造を確認 |

**主要処理フロー**:
1. **37行目**: `selectedAssistantId` をルートパラメータから取得
2. **44-50行目**: `backUrl` computed でFAQ一覧へのリンク生成
3. **53-55行目**: `filteredResponses` でpending以外を除外
4. **61-75行目**: `handleAccept()` で単体承認処理
5. **183-197行目**: `handleBulkApprove()` で一括承認処理

#### Step 3: 一括操作の拡張を理解する

一括承認ボタンの追加実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Pending.vue | `app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue` | BulkSelectBarの#secondary-actionsスロットを確認（300-309行目） |

**主要処理フロー**:
- 一括承認ボタンはBulkSelectBarのsecondary-actionsスロットに配置
- クリックで `handleBulkApprove()` を呼び出し

#### Step 4: API通信層を理解する

バックエンドとの通信処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | response.js (api) | `app/javascript/dashboard/api/captain/response.js` | status='pending'でのget呼び出しを確認 |

### プログラム呼び出し階層図

```
Pending.vue
    |
    +-- PageLayout.vue
    |       |
    |       +-- backUrl設定でFAQ一覧へのリンク
    |
    +-- Input.vue (検索)
    |       |
    |       +-- @input -> debouncedSearch()
    |
    +-- BulkSelectBar.vue
    |       |
    |       +-- 一括選択/解除
    |       +-- 一括削除
    |       +-- #secondary-actions
    |               |
    |               +-- 一括承認ボタン -> handleBulkApprove()
    |
    +-- LimitBanner.vue
    |
    +-- ResponseCard.vue (複数)
    |       |
    |       +-- show-actions=true (アクションボタン表示)
    |       +-- show-menu=false (メニュー非表示)
    |       +-- @action -> handleAction() (approve/edit/delete)
    |
    +-- DeleteDialog.vue
    |
    +-- BulkDeleteDialog.vue
    |
    +-- CreateResponseDialog.vue
```

### データフロー図

```
[入力]                    [処理]                           [出力]

URLアクセス ──────────▶ onMounted
                              │
                              └── initializeFromURL()
                                      │
                                      ▼
                        GET /api/v1/.../captain/assistant_responses
                        (status=pending)
                              │
                              ▼
                        Vuex State更新
                              │
                              ▼
                        filteredResponses (追加フィルタ)
                              │
                              ▼
                        ResponseCard描画 ────────▶ 保留中FAQ一覧

承認ボタン ────────────▶ handleAccept()
                              │
                              ▼
                        captainResponses/update
                        (status='approved')
                              │
                              ▼
                        filteredResponsesから除外

一括承認 ────────────▶ handleBulkApprove()
                              │
                              ▼
                        captainBulkActions/handleBulkApprove
                              │
                              ▼
                        fetchResponseAfterBulkAction()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Pending.vue | `app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue` | ソース | メイン画面コンポーネント |
| captain.routes.js | `app/javascript/dashboard/routes/dashboard/captain/captain.routes.js` | 設定 | ルーティング定義 |
| response.js (store) | `app/javascript/dashboard/store/captain/response.js` | ソース | Vuexストアモジュール |
| bulkActions.js | `app/javascript/dashboard/store/captain/bulkActions.js` | ソース | 一括操作ストア |
| response.js (api) | `app/javascript/dashboard/api/captain/response.js` | ソース | APIクライアント |
| ResponseCard.vue | `app/javascript/dashboard/components-next/captain/assistant/ResponseCard.vue` | ソース | FAQカードコンポーネント |
| BulkSelectBar.vue | `app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue` | ソース | 一括選択バー |
| CreateResponseDialog.vue | `app/javascript/dashboard/components-next/captain/pageComponents/response/CreateResponseDialog.vue` | ソース | 編集ダイアログ |
| ResponsePageEmptyState.vue | `app/javascript/dashboard/components-next/captain/pageComponents/emptyStates/ResponsePageEmptyState.vue` | ソース | 空状態表示 |
