# 画面設計書 18-インボックスビュー一覧

## 概要

本ドキュメントは、Chatwootのインボックスビュー一覧画面の設計仕様を記述したものです。通知ベースの新しいインボックスUIで、ユーザーへの通知を会話形式で表示する画面です。

### 本画面の処理概要

**業務上の目的・背景**：
インボックスビューは、従来の会話一覧とは異なるアプローチで、通知（Notification）を中心とした会話管理を提供します。エージェントは自分に関連する通知（新規メッセージ、メンション、割り当て変更など）を一元的に確認し、効率的に対応できます。この画面は特に、複数のインボックスを担当するエージェントにとって、重要な通知を見逃さないための集約ビューとして機能します。

**画面へのアクセス方法**：
1. サイドバーの「Inbox」リンクをクリック
2. URL直接アクセス: `/app/accounts/:accountId/inbox-view`

**主要な操作・処理内容**：
1. 通知一覧の表示（会話に関連する通知）
2. ステータスフィルター（Read/Unread）による絞り込み
3. タイプフィルター（通知タイプ）による絞り込み
4. ソート順の変更（新しい順/古い順）
5. 通知の既読/未読マーク
6. 通知の削除
7. 通知から会話詳細への遷移
8. 無限スクロールによる追加読み込み

**画面遷移**：
- 遷移元: ダッシュボードホーム画面（サイドバーのInboxリンク）
- 遷移先: インボックスビュー詳細画面（通知クリック時）

**権限による表示制御**：
- administrator: 全機能へのフルアクセス
- agent: 自分宛ての通知の閲覧・管理
- すべてのCONVERSATION_PERMISSIONSを持つロール

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 会話CRUD | 主機能 | 新UIでの会話一覧表示 |
| 17 | インボックス基本管理 | 補助機能 | インボックスビューの表示 |

## 画面種別

一覧

## URL/ルーティング

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

## 入出力項目

### ルートパラメータ

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

### フィルター入力

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| status | String | No | 既読状態フィルター（read/unread） |
| type | String | No | 通知タイプフィルター |
| sortOrder | String | No | ソート順（newest/oldest） |

## 表示項目

### ヘッダー部

| 項目名 | 型 | 説明 |
|--------|-----|------|
| filter_dropdown | Component | フィルター選択ドロップダウン |
| sort_dropdown | Component | ソート順選択ドロップダウン |
| option_menu | Component | オプションメニュー |

### 通知カード（InboxCard）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| notification_id | Number | 通知ID |
| notification_type | String | 通知タイプ（assigned, mentioned, etc.） |
| primary_actor | Object | 関連する会話情報 |
| conversation_id | Number | 関連する会話ID |
| inbox_icon | Icon | インボックスのアイコン |
| contact_name | String | 連絡先名 |
| message_preview | String | メッセージプレビュー |
| timestamp | DateTime | 通知日時 |
| read_at | DateTime | 既読日時（nullなら未読） |
| inbox_name | String | インボックス名 |

### 空状態表示

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

## イベント仕様

### 1-通知一覧取得

**トリガー**: 画面マウント時またはフィルター変更時

**処理フロー**:
1. onMountedでsetSavedFilter()とfetchNotifications()を実行
2. UISettingsから保存済みフィルター設定を復元
3. notifications/indexアクションでAPI呼び出し
4. 通知一覧をストアに保存
5. InboxCardコンポーネントで表示

**Vuexアクション**: `notifications/index`

### 2-通知クリック（会話を開く）

**トリガー**: InboxCardのクリック

**処理フロー**:
1. openConversation()が呼び出される
2. notifications/readアクションで既読マーク
3. notifications/unReadCountで未読カウント更新
4. router.pushでinbox_view_conversationルートへ遷移
5. InboxView.vueで会話詳細を表示

**Vuexアクション**: `notifications/read`, `notifications/unReadCount`

### 3-フィルター変更

**トリガー**: フィルタードロップダウンで選択変更

**処理フロー**:
1. onFilterChange()が呼び出される
2. status/type/sortOrderの更新
3. fetchNotifications()で通知一覧を再取得
4. notificationFiltersのwatchでストアのフィルター更新

**Vuexアクション**: `notifications/updateNotificationFilters`, `notifications/index`

### 4-通知既読マーク

**トリガー**: コンテキストメニューから「既読にする」選択

**処理フロー**:
1. markNotificationAsRead()が呼び出される
2. notifications/readアクションでAPI呼び出し
3. 成功通知の表示
4. notifications/unReadCountで未読カウント更新

**Vuexアクション**: `notifications/read`, `notifications/unReadCount`

### 5-通知削除

**トリガー**: コンテキストメニューから「削除」選択

**処理フロー**:
1. deleteNotification()が呼び出される
2. redirectToInbox()でinbox_viewへリダイレクト
3. notifications/deleteアクションでAPI呼び出し
4. 成功通知の表示

**Vuexアクション**: `notifications/delete`

### 6-無限スクロール

**トリガー**: リストの下部へスクロール

**処理フロー**:
1. IntersectionObserverでobservedイベント発火
2. loadMoreNotifications()が呼び出される
3. pageをインクリメント
4. notifications/indexアクションで追加ページを取得
5. 既存リストに追加

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 通知一覧取得 | notifications | SELECT | 通知一覧の取得 |
| 通知既読マーク | notifications | UPDATE | read_atの更新 |
| 通知未読マーク | notifications | UPDATE | read_atをnullに |
| 通知削除 | notifications | DELETE | 通知の削除 |

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

#### notifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = current_user_id | ページネーション付き |
| UPDATE | read_at | 現在日時 | 既読マーク時 |
| UPDATE | read_at | NULL | 未読マーク時 |
| DELETE | * | id = notification_id | |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| INBOX.LIST.NO_NOTIFICATIONS | 情報 | 通知がありません | 通知が0件 |
| INBOX.ALERTS.MARK_AS_READ | 成功 | 既読にしました | 既読マーク成功時 |
| INBOX.ALERTS.MARK_AS_UNREAD | 成功 | 未読にしました | 未読マーク成功時 |
| INBOX.ALERTS.DELETE | 成功 | 削除しました | 削除成功時 |

## 例外処理

| 例外状態 | 表示内容 | 処理 |
|---------|---------|------|
| 通知が0件 | 空状態メッセージ表示 | NO_NOTIFICATIONSメッセージ |
| ネットワークエラー | ローディング継続または再試行 | |
| 通知取得失敗 | サイレントエラー | catchブロックで処理 |

## 備考

- 新しいインボックスUIで、従来のConversationViewとは別系統
- 通知ベースのため、メンション・割り当て変更なども含む
- UISettingsに保存されたフィルター設定を復元
- CmdBarConversationSnoozeコンポーネントでスヌーズ機能も利用可能
- IntersectionObserverで無限スクロールを実装

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inbox/routes.js | `app/javascript/dashboard/routes/dashboard/inbox/routes.js` | インボックスビューのルーティング構造 |
| 1-2 | notifications/index.js | `app/javascript/dashboard/store/modules/notifications/index.js` | 通知ストアの状態構造 |

**読解のコツ**: 通知（Notification）と会話（Conversation）の関係を理解してください。

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

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

**主要処理フロー**:
1. **行23-28**: refによる状態管理（page, status, type, sortOrder）
2. **行35-38**: mapGetterで通知データとUIフラグを取得
3. **行65-70**: fetchNotifications - 通知一覧取得
4. **行82-92**: loadMoreNotifications - 追加読み込み
5. **行168-201**: openConversation - 通知から会話を開く
6. **行217-221**: onMounted処理

#### Step 3: 通知カードコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InboxCard.vue | `app/javascript/dashboard/components-next/Inbox/InboxCard.vue` | 通知カードの表示ロジック |

#### Step 4: ストアアクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | notifications/actions.js | `app/javascript/dashboard/store/modules/notifications/actions.js` | 通知関連アクション |

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

```
InboxList.vue (ルートコンポーネント)
    |
    +-- InboxListHeader.vue (ヘッダー・フィルター)
    |
    +-- InboxCard.vue (通知カード - 複数)
    |       |
    |       +-- InboxContextMenu.vue (右クリックメニュー)
    |
    +-- IntersectionObserver.vue (無限スクロール)
    |
    +-- CmdBarConversationSnooze.vue (スヌーズ)
    |
    +-- <router-view /> (InboxView.vueまたはInboxEmptyState.vue)
```

### データフロー図

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

URL params          --> Vue Router                --> InboxList.vue
(/inbox-view)           (route matching)
                                                          |
                                                          v
UISettings          --> setSavedFilter()          --> フィルター復元
                                                          |
                                                          v
                    --> notifications/index       --> API Request
                        (Vuex action)                 (GET /notifications)
                                                          |
                                                          v
                    --> Vuex Store                --> 通知一覧表示
                        (notifications)               (InboxCard)

Click event         --> openConversation()        --> notifications/read
                                                          |
                                                          v
                    --> router.push               --> InboxView.vue
                        (inbox_view_conversation)     (会話詳細)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| InboxList.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxList.vue` | ソース | インボックスビュー一覧 |
| routes.js | `app/javascript/dashboard/routes/dashboard/inbox/routes.js` | ソース | ルーティング定義 |
| InboxListHeader.vue | `app/javascript/dashboard/routes/dashboard/inbox/components/InboxListHeader.vue` | ソース | ヘッダーコンポーネント |
| InboxCard.vue | `app/javascript/dashboard/components-next/Inbox/InboxCard.vue` | ソース | 通知カードコンポーネント |
| InboxView.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxView.vue` | ソース | 会話詳細表示 |
| InboxEmptyState.vue | `app/javascript/dashboard/routes/dashboard/inbox/InboxEmptyState.vue` | ソース | 空状態表示 |
| notifications/index.js | `app/javascript/dashboard/store/modules/notifications/index.js` | ソース | 通知ストア |
| notifications/actions.js | `app/javascript/dashboard/store/modules/notifications/actions.js` | ソース | 通知アクション |
| notifications/getters.js | `app/javascript/dashboard/store/modules/notifications/getters.js` | ソース | 通知ゲッター |
