# 画面設計書 51-インボックスエージェント追加

## 概要

本ドキュメントは、Chatwootのインボックスエージェント追加画面の設計書です。インボックス作成フローの一部として、新規インボックスに担当エージェントを追加する機能を提供します。

### 本画面の処理概要

インボックスにエージェント（担当者）を追加するための画面です。インボックス作成ウィザードのステップとして動作し、選択したエージェントをインボックスのメンバーとして登録します。

**業務上の目的・背景**：インボックス（受信トレイ）は特定のチャネル（Webチャット、メール、SNSなど）からの問い合わせを受け取る単位です。適切なエージェントをインボックスに割り当てることで、そのチャネルからの問い合わせに対応できる担当者を明確にし、効率的なチーム運営を実現します。

**画面へのアクセス方法**：設定メニュー > インボックス > 新規作成 > チャネル設定完了後に自動遷移、または既存インボックスの設定画面からエージェント管理へアクセス

**主要な操作・処理内容**：
1. 登録済みエージェント一覧からエージェントを複数選択
2. マルチセレクトUIでエージェントを追加・削除
3. 「エージェント追加」ボタン押下でインボックスメンバーを更新
4. 成功時は設定完了画面へ自動遷移

**画面遷移**：
- 遷移元: チャネル設定画面（ChannelFactory）
- 遷移先: インボックス設定完了画面（FinishSetup）

**権限による表示制御**：管理者（administrator）のみがこの画面にアクセス可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | インボックスメンバー管理 | 主機能 | インボックスへのエージェント追加 |

## 画面種別

登録（ウィザード形式の中間ステップ）

## URL/ルーティング

- パス: `/app/accounts/:accountId/settings/inboxes/new/:inbox_id/agents`
- ルート名: `settings_inboxes_add_agents`
- 権限: administrator

## 入出力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| selectedAgents | Array<Agent> | Yes | 選択されたエージェントのリスト |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|------|------|
| agentList | Array<Agent> | システムに登録されている全エージェント一覧 |
| agent.id | Number | エージェントID |
| agent.name | String | エージェント名（マルチセレクトで表示） |

## イベント仕様

### 1-フォーム送信（addAgents）

**トリガー**: 「エージェント追加」ボタン押下

**処理フロー**:
1. `isCreating`フラグをtrueに設定（ボタンのローディング表示）
2. ルートパラメータから`inbox_id`を取得
3. 選択されたエージェントからIDリストを抽出
4. `InboxMembersAPI.update()`でサーバーにPATCHリクエスト送信
5. 成功時: `settings_inbox_finish`画面へ遷移
6. 失敗時: エラーメッセージをアラート表示
7. `isCreating`フラグをfalseに設定

### 2-エージェント選択

**トリガー**: マルチセレクトでエージェントを選択/選択解除

**処理フロー**:
1. Vuelidateによるバリデーション実行（`v$.selectedAgents.$touch`）
2. `selectedAgents`配列を更新

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| エージェント追加ボタン押下 | inbox_members | UPDATE（全置換） | インボックスに所属するエージェントを更新 |

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

#### inbox_members

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE/INSERT | user_id | 選択されたエージェントのIDリスト | 既存のメンバーを削除後、新しいメンバーを追加 |
| DELETE/INSERT | inbox_id | URLパラメータのinbox_id | 対象インボックス |

## メッセージ仕様

| 種別 | キー | 表示条件 | メッセージ内容 |
|------|------|----------|--------------|
| エラー | INBOX_MGMT.ADD.AGENTS.VALIDATION_ERROR | エージェント未選択時 | バリデーションエラー |
| エラー | error.message | API呼び出し失敗時 | サーバーから返されたエラーメッセージ |

## 例外処理

| 例外状況 | 対応処理 |
|----------|----------|
| エージェント未選択 | バリデーションエラーメッセージを表示、送信ボタン無効化 |
| API通信エラー | `useAlert(error.message)`でエラーメッセージをトースト表示 |
| 権限不足 | ルートガードにより画面アクセス自体をブロック |

## 備考

- この画面はインボックス作成ウィザードの一部として動作
- エージェント一覧は画面マウント時にVuexストアから取得
- マルチセレクトコンポーネントは複数選択・検索機能を提供

---

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

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

### 推奨読解順序

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

インボックスメンバーのAPIリクエスト/レスポンス形式を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inboxMembers.js | `app/javascript/dashboard/api/inboxMembers.js` | APIクライアントの構造、updateメソッドのリクエスト形式 |

**読解のコツ**: `ApiClient`を継承したクラスで、`update`メソッドがPATCHリクエストを送信。`inbox_id`と`user_ids`をボディに含む。

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

Vueコンポーネントの構造と状態管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AddAgents.vue | `app/javascript/dashboard/routes/dashboard/settings/inbox/AddAgents.vue` | コンポーネントの構造、フォーム送信処理 |

**主要処理フロー**:
1. **L38-39**: マウント時に`agents/get`アクションでエージェント一覧を取得
2. **L42-60**: `addAgents()`メソッドでフォーム送信処理
3. **L48**: `InboxMembersAPI.update()`でサーバー更新
4. **L49-55**: 成功時に`settings_inbox_finish`へルーター遷移

#### Step 3: ルーティング設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inbox.routes.js | `app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js` | ルート定義、権限設定、遷移関係 |

**主要処理フロー**:
- **L86-93**: `settings_inboxes_add_agents`ルートの定義
- **L89**: `permissions: ['administrator']`で管理者限定

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

```
AddAgents.vue (コンポーネント)
    │
    ├─ mounted()
    │      └─ $store.dispatch('agents/get')
    │             └─ AgentsAPI.get()
    │
    └─ addAgents()
           ├─ InboxMembersAPI.update({ inboxId, agentList })
           │      └─ axios.patch('/inbox_members', { inbox_id, user_ids })
           │
           └─ router.replace({ name: 'settings_inbox_finish' })
```

### データフロー図

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

agentList ──────────────▶ マルチセレクト ──────────────▶ selectedAgents
(Vuex Store)              (ユーザー選択)                  (ローカルstate)
                                │
                                ▼
                          addAgents()
                                │
                                ▼
selectedAgents ──────────▶ InboxMembersAPI.update() ──▶ inbox_members
(選択済みエージェント)      (PATCH /inbox_members)         (DBテーブル)
                                │
                                ▼
                          router.replace()
                                │
                                ▼
                          FinishSetup.vue
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AddAgents.vue | `app/javascript/dashboard/routes/dashboard/settings/inbox/AddAgents.vue` | ソース | メインコンポーネント |
| inboxMembers.js | `app/javascript/dashboard/api/inboxMembers.js` | ソース | API通信クライアント |
| inbox.routes.js | `app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js` | ソース | ルーティング定義 |
| SettingsSubPageHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/inbox/SettingsSubPageHeader.vue` | ソース | ヘッダーコンポーネント |
| Button.vue | `app/javascript/dashboard/components-next/button/Button.vue` | ソース | ボタンコンポーネント |
