# 画面設計書 57-チームエージェント追加画面

## 概要

本ドキュメントは、Chatwootのチームエージェント追加画面の設計書です。チーム作成ウィザードの第2ステップとして、作成したチームにエージェントを追加する画面です。

### 本画面の処理概要

新規作成したチームにエージェント（担当者）を追加する画面です。登録済みの全エージェントから複数選択してチームメンバーとして登録します。

**業務上の目的・背景**：チーム作成後、そのチームに所属するエージェントを指定することで、チーム単位での会話割り当てや権限管理が可能になります。チェックボックス形式で複数のエージェントを一括選択できます。

**画面へのアクセス方法**：チーム新規作成画面でチーム作成後に自動遷移

**主要な操作・処理内容**：
1. エージェント一覧の表示（チェックボックス付き）
2. 全選択機能
3. 個別エージェントの選択/選択解除
4. 選択したエージェントをチームに追加して次画面へ遷移

**画面遷移**：
- 遷移元: チーム新規作成画面（CreateTeam）
- 遷移先: チーム設定完了画面（FinishSetup）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | チーム管理 | 主機能 | チームへのエージェント追加 |

## 画面種別

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

## URL/ルーティング

- パス: `/app/accounts/:accountId/settings/teams/new/:teamId/agents`
- ルート名: `settings_teams_add_agents`
- 権限: administrator

## 入出力項目

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

## 表示項目

| 項目名 | 型 | 説明 |
|--------|------|------|
| agentList | Array<Agent> | 全エージェント一覧 |
| agent.id | Number | エージェントID |
| agent.name | String | エージェント名 |
| agent.email | String | メールアドレス |
| agent.thumbnail | String | アバター画像URL |
| agent.availability_status | String | オンライン状態 |
| selectedAgentCount | Number | 選択済みエージェント数 |
| currentTeam.name | String | 現在のチーム名（ヘッダー表示用） |

## イベント仕様

### 1-エージェント選択（handleSelectAgent）

**トリガー**: エージェント行のチェックボックスをクリック

**処理フロー**:
1. 既に選択済みかどうかを判定（`isAgentSelected`）
2. 選択済みの場合: `selectedAgents`から削除
3. 未選択の場合: `selectedAgents`に追加
4. `updateSelectedAgents()`で親コンポーネントへ通知

### 2-全選択（selectAllAgents）

**トリガー**: ヘッダーの全選択チェックボックスをクリック

**処理フロー**:
1. 全エージェントのIDを抽出
2. `updateSelectedAgents()`で全エージェントを選択状態に

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

**トリガー**: 「次へ」ボタン押下

**処理フロー**:
1. `isCreating`フラグをtrueに設定
2. `store.dispatch('teamMembers/create', { teamId, agentsList })`を実行
3. 成功時: `settings_teams_finish`へ遷移、チーム一覧を再取得
4. 失敗時: エラーメッセージをアラート表示
5. `isCreating`フラグをfalseに設定

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| エージェント追加 | team_members | INSERT | チームメンバーを追加 |

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

#### team_members

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | team_id | URLパラメータのteamId | 対象チーム |
| INSERT | user_id | 選択されたエージェントのID | 複数レコード |

## メッセージ仕様

| 種別 | キー | 表示条件 | メッセージ内容 |
|------|------|----------|--------------|
| エラー | TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR | エージェント未選択時 | エージェント選択必須エラー |
| エラー | error.message | API呼び出し失敗時 | サーバーから返されたエラーメッセージ |
| 情報 | TEAMS_SETTINGS.AGENTS.SELECTED_COUNT | 常時（フッター） | 選択数 / 総数 |

## 例外処理

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

## 備考

- AgentSelectorコンポーネントを使用（チーム作成・編集共通）
- エージェント一覧は画面マウント時に取得（`agents/get`アクション）
- 選択数はリアルタイムで表示更新

---

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

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

### 推奨読解順序

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

チームメンバーのAPIリクエスト形式を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | teamMembers.js | `app/javascript/dashboard/store/modules/teamMembers.js` | Vuexストアの構造、createアクション |
| 1-2 | teams.js | `app/javascript/dashboard/api/teams.js` | addAgents APIメソッド |

**読解のコツ**: `TeamsAPI.addAgents()`はPOSTリクエストで`user_ids`配列を送信する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AddAgents.vue | `app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue` | メインコンポーネント |
| 2-2 | AgentSelector.vue | `app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue` | エージェント選択コンポーネント |

**主要処理フロー**:
1. **AddAgents L52-53**: マウント時にエージェント一覧を取得
2. **AddAgents L64-85**: `addAgents()`メソッドでチームメンバー作成
3. **AddAgents L69-72**: ストアディスパッチでチームメンバー追加
4. **AgentSelector L50-60**: `handleSelectAgent()`でエージェント選択処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | teams.routes.js | `app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js` | ウィザードフロー |

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

```
AddAgents.vue (コンポーネント)
    │
    ├─ mounted()
    │      └─ store.dispatch('agents/get')
    │
    └─ AgentSelector.vue (子コンポーネント)
           │
           ├─ handleSelectAgent(agentId)
           │      └─ updateSelectedAgents(result)
           │             └─ 親コンポーネントへコールバック
           │
           ├─ selectAllAgents()
           │      └─ updateSelectedAgents(allAgentIds)
           │
           └─ submit
                  │
                  ▼
           addAgents() [AddAgents.vue]
                  │
                  ├─ store.dispatch('teamMembers/create', { teamId, agentsList })
                  │      └─ TeamsAPI.addAgents({ teamId, agentsList })
                  │             └─ POST /api/v1/accounts/:id/teams/:teamId/team_members
                  │
                  ├─ router.replace({ name: 'settings_teams_finish' })
                  │
                  └─ store.dispatch('teams/get')
```

### データフロー図

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

store.dispatch('agents/get')
        │
        ▼
agentList ───────────────▶ AgentSelector
(全エージェント)                │
                               ├─ チェックボックス操作
                               │
                               ▼
                         handleSelectAgent()
                               │
                               ▼
                         updateSelectedAgents()
                               │
                               ▼
selectedAgents ◀───────────────┘
        │
        ▼
addAgents() submit
        │
        ▼
store.dispatch('teamMembers/create')
        │
        ▼
TeamsAPI.addAgents()
        │
        ▼
team_members (DBテーブル)
        │
        ▼
router.replace()
(設定完了画面へ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AddAgents.vue | `app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue` | ソース | メインコンポーネント |
| AgentSelector.vue | `app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue` | ソース | エージェント選択コンポーネント |
| teamMembers.js | `app/javascript/dashboard/store/modules/teamMembers.js` | ソース | Vuexストア |
| teams.js | `app/javascript/dashboard/api/teams.js` | ソース | APIクライアント |
| teams.routes.js | `app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js` | ソース | ルーティング定義 |
| SettingsSubPageHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/inbox/SettingsSubPageHeader.vue` | ソース | ヘッダーコンポーネント |
| Avatar.vue | `app/javascript/next/avatar/Avatar.vue` | ソース | アバターコンポーネント |
