# 画面設計書 19-インボックスビュー詳細

## 概要

本ドキュメントは、Chatwootのインボックスビュー詳細画面の設計仕様を記述したものです。インボックスビュー一覧から選択された会話の詳細を表示する画面です。

### 本画面の処理概要

**業務上の目的・背景**：
インボックスビュー詳細画面は、インボックスビュー一覧で選択した通知に関連する会話の詳細を表示します。従来のConversationViewとは異なり、通知リストと会話詳細が並列で表示され、ワンクリックで次の通知へ移動できるナビゲーション機能を提供します。これにより、エージェントは効率的に複数の通知を処理できます。

**画面へのアクセス方法**：
1. インボックスビュー一覧で通知カードをクリック
2. URL直接アクセス: `/app/accounts/:accountId/inbox-view/:type/:id`

**主要な操作・処理内容**：
1. 選択した会話の詳細表示
2. メッセージの閲覧と送信
3. 前後の通知へのナビゲーション
4. コンタクトサイドバーの表示/非表示
5. 会話のステータス変更、割り当て変更などの操作

**画面遷移**：
- 遷移元: インボックスビュー一覧（通知クリック時）
- 遷移先: 前後の会話詳細（ナビゲーションボタン）

**権限による表示制御**：
- administrator: 全機能へのフルアクセス
- agent: 基本的な会話閲覧・操作
- すべてのCONVERSATION_PERMISSIONSを持つロール

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 会話CRUD | 主機能 | 会話詳細の表示 |
| 43 | メッセージ送受信 | 主機能 | メッセージの送受信 |

## 画面種別

詳細

## URL/ルーティング

| ルート名 | パス | 説明 |
|---------|------|------|
| inbox_view_conversation | `/accounts/:accountId/inbox-view/:type/:id` | インボックスビュー詳細 |

## 入出力項目

### ルートパラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| accountId | Number | Yes | アカウントID |
| type | String | Yes | 通知タイプ（'conversation'など） |
| id | Number | Yes | 会話ID |

### コンポーネントProps（InboxListから渡される）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| inboxId | Number | No | インボックスID |
| conversationId | Number | Yes | 会話ID（route.params.idから） |

## 表示項目

### ヘッダー部（InboxItemHeader）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| total_length | Number | 通知総数 |
| current_index | Number | 現在の通知インデックス |
| prev_button | Button | 前の通知へ移動 |
| next_button | Button | 次の通知へ移動 |
| notification_info | Object | 現在のアクティブ通知情報 |

### 会話詳細（ConversationBox）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| conversation_header | Component | 会話ヘッダー |
| messages_view | Component | メッセージ一覧と入力 |
| dashboard_apps | Component | ダッシュボードアプリタブ |

### コンタクトサイドバー

| 項目名 | 型 | 説明 |
|--------|-----|------|
| contact_panel | Component | 連絡先パネル |
| is_visible | Boolean | UISettingsに基づく表示状態 |

### 空状態表示

| 項目名 | 型 | 説明 |
|--------|-----|------|
| empty_state_message | String | 「メッセージがありません」等のメッセージ |

## イベント仕様

### 1-会話詳細取得

**トリガー**: 画面マウント時またはconversationIdの変更

**処理フロー**:
1. watchでconversationIdの変更を監視
2. fetchConversationById()が呼び出される
3. clearSelectedState()で以前の選択状態をクリア
4. 既存の会話をfindConversation()で検索
5. 存在しない場合はgetConversationでAPI取得
6. setActiveChat()で選択会話を設定
7. SCROLL_TO_MESSAGEイベントを発火

**Vuexアクション**: `clearSelectedState`, `getConversation`, `setActiveChat`

### 2-前後ナビゲーション

**トリガー**: InboxItemHeaderの前/次ボタンクリック

**処理フロー**:
1. onClickNext()またはonClickPrev()が呼び出される
2. navigateToConversation()で次/前のインデックスを計算
3. 対象の通知をnotificationsから取得
4. openNotification()で通知を開く
5. notifications/readで既読マーク
6. router.pushでinbox_view_conversationルートへ遷移

### 3-コンタクトパネル表示切り替え

**トリガー**: SidepanelSwitchのトグル

**処理フロー**:
1. isContactPanelOpenがUISettingsから計算される
2. updateUISettingsでis_contact_sidebar_openを更新
3. ConversationSidebarの表示/非表示が切り替わる

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 会話詳細取得 | conversations | SELECT | 会話詳細の取得 |
| メッセージ取得 | messages | SELECT | メッセージ一覧の取得 |
| 通知既読マーク | notifications | UPDATE | read_atの更新 |

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

（ConversationBoxを使用するため、会話詳細画面と同様）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| INBOX.LIST.NO_MESSAGES_AVAILABLE | 情報 | メッセージがありません | 会話未選択または取得失敗時 |

## 例外処理

| 例外状態 | 表示内容 | 処理 |
|---------|---------|------|
| 会話未選択 | InboxEmptyState表示 | 空状態コンポーネント表示 |
| 会話取得中 | ローディングスピナー | Spinnerコンポーネント表示 |
| 会話取得失敗 | サイレントエラー | catchブロックで処理 |

## 備考

- InboxList.vueの子コンポーネントとしてrouter-viewで表示される
- ConversationBoxコンポーネントを再利用
- isInboxView propをtrueで渡すことで、インボックスビュー固有の動作を有効化
- 前後ナビゲーションは通知リストに基づく
- activeNotificationIndexで現在位置を追跡

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inbox/routes.js | `app/javascript/dashboard/routes/dashboard/inbox/routes.js` | インボックスビュー詳細のルーティング |

**読解のコツ**: InboxList.vueの子ルートとしてInboxView.vueが設定されていることを確認してください。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | InboxView.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxView.vue` | インボックスビュー詳細のメインコンポーネント |

**主要処理フロー**:
1. **行25-26**: mapGetterでnotification, currentChatを取得
2. **行31-32**: computedでinboxIdとconversationIdを取得
3. **行40-44**: activeNotificationで現在の通知を特定
4. **行69-75**: isContactPanelOpenでサイドバー表示状態を判定
5. **行114-124**: setActiveChatで選択会話を設定
6. **行126-147**: fetchConversationByIdで会話詳細を取得
7. **行149-162**: navigateToConversationで前後ナビゲーション

#### Step 3: ヘッダーコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InboxItemHeader.vue | `app/javascript/dashboard/routes/dashboard/inbox/components/InboxItemHeader.vue` | ナビゲーションヘッダー |

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

```
InboxList.vue (親コンポーネント)
    |
    +-- <router-view />
            |
            +-- InboxView.vue (詳細コンポーネント)
                    |
                    +-- InboxItemHeader.vue (ナビゲーションヘッダー)
                    |       |
                    |       +-- PaginationButton.vue (前/次ボタン)
                    |
                    +-- ConversationBox.vue (会話詳細)
                    |       |
                    |       +-- ConversationHeader.vue
                    |       +-- MessagesView.vue
                    |       +-- SidepanelSwitch.vue
                    |
                    +-- ConversationSidebar.vue (コンタクトパネル)
                            |
                            +-- ContactPanel.vue
```

### データフロー図

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

URL params          --> Vue Router                --> InboxView.vue
(/inbox-view/:type/:id) (route matching)              (conversationId)
                                                          |
                                                          v
                    --> Vuex Store                --> notification
                        (notifications module)        (activeNotification)
                                                          |
                                                          v
                    --> fetchConversationById()   --> getConversation
                                                      (API呼び出し)
                                                          |
                                                          v
                    --> setActiveChat()           --> currentChat
                                                      (選択会話設定)
                                                          |
                                                          v
                    --> ConversationBox.vue       --> 会話詳細表示

Navigation          --> navigateToConversation()  --> openNotification()
(prev/next click)                                         |
                                                          v
                    --> router.push               --> URL変更
                        (inbox_view_conversation)     (新しい会話)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| InboxView.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxView.vue` | ソース | インボックスビュー詳細 |
| routes.js | `app/javascript/dashboard/routes/dashboard/inbox/routes.js` | ソース | ルーティング定義 |
| InboxItemHeader.vue | `app/javascript/dashboard/routes/dashboard/inbox/components/InboxItemHeader.vue` | ソース | ナビゲーションヘッダー |
| InboxEmptyState.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxEmptyState.vue` | ソース | 空状態表示 |
| ConversationBox.vue | `app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue` | ソース | 会話詳細（共通） |
| ConversationSidebar.vue | `app/javascript/dashboard/components/widgets/conversation/ConversationSidebar.vue` | ソース | コンタクトサイドバー |
| SidepanelSwitch.vue | `app/javascript/dashboard/components-next/Conversation/SidepanelSwitch.vue` | ソース | サイドパネル切り替え |
