# 画面設計書 117-未読メッセージ画面

## 概要

本ドキュメントは、Chatwootのチャットウィジェットにおける未読メッセージ画面の設計書です。ウィジェットバブルをクリックした際に未読メッセージがある場合に表示される画面です。

### 本画面の処理概要

**業務上の目的・背景**：未読メッセージ画面は、顧客がウィジェットを開いた際にエージェントからの未読メッセージを目立つ形で表示するための画面です。これにより、顧客は重要なメッセージを見逃すことなく、迅速に対応できます。ウィジェットバブルに表示される未読カウントと連動し、顧客エンゲージメントの向上に貢献します。

**画面へのアクセス方法**：ウィジェットバブルをクリックした際に、未読メッセージが存在する場合に自動的に表示されます。URLハッシュパスは `/unread-messages` です。

**主要な操作・処理内容**：
1. 未読メッセージの一覧表示
2. メッセージ送信者情報の表示
3. 閉じるボタンでウィジェットを閉じる
4. 「View Messages」ボタンでフル会話画面へ遷移

**画面遷移**：
- 遷移元：ウィジェットバブル（未読時）
- 遷移先：メッセージ画面（「View Messages」クリック時）

**権限による表示制御**：ウィジェットはWebサイト訪問者向けのため、特別な権限制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 162 | Widgetメッセージ | 主機能 | 未読メッセージの通知表示 |

## 画面種別

通知・一覧画面

## URL/ルーティング

- パス: `#/unread-messages`（ウィジェット内ハッシュルーティング）
- ルート名: `unread-messages`
- コンポーネント: `UnreadMessages.vue`

## 入出力項目

### 入力項目

本画面には入力項目はありません。

### 出力項目

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| 未読メッセージ一覧 | messages | array | 未読のテキストメッセージ配列 |

## 表示項目

### 閉じるボタンエリア

| 項目名 | 説明 |
|--------|------|
| 閉じるボタン | ウィジェットを閉じるボタン |

### メッセージ一覧エリア

| 項目名 | 説明 |
|--------|------|
| 送信者情報 | 最初のメッセージの送信者名とアバター |
| メッセージバブル | 各未読メッセージの内容表示 |

### アクションエリア

| 項目名 | 説明 |
|--------|------|
| View Messages ボタン | フル会話画面へ遷移するボタン |

## イベント仕様

### 1-ウィジェット閉じる

**トリガー**: 閉じるボタンクリック

**処理フロー**:
1. `closeFullView`メソッド呼び出し
2. iframe内かどうかを確認（`IFrameHelper.isIFrame()`）
3. iframe内の場合、親ページへ`toggleBubble`イベントを送信
4. ウィジェットが閉じる

### 2-会話画面へ遷移

**トリガー**: 「View Messages」ボタンクリック

**処理フロー**:
1. `openConversationView`メソッド呼び出し
2. `ON_UNREAD_MESSAGE_CLICK`イベントをemitterで発火
3. 親コンポーネントまたはSDKがイベントを受信
4. メッセージ画面へ遷移

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面ではDBへの直接更新なし |

本画面は表示専用であり、データベースへの更新は行いません。

## メッセージ仕様

| 種別 | キー | メッセージ内容 | 表示タイミング |
|------|-----|---------------|---------------|
| ボタン | UNREAD_VIEW.CLOSE_MESSAGES_BUTTON | メッセージを閉じる | 閉じるボタン |
| ボタン | UNREAD_VIEW.VIEW_MESSAGES_BUTTON | メッセージを見る | View Messagesボタン |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 未読メッセージなし | 本画面は表示されない（ルーティングで制御） |
| iframe外で実行 | IFrameHelper判定によりpostMessage送信をスキップ |

## 備考

- ウィジェットバブル上の未読カウントと連動
- 親ページとの通信はpostMessage（IFrameHelper）を使用
- 複数の未読メッセージがある場合、最初のメッセージの送信者情報のみ表示
- 添付ファイルのみのメッセージは絵文字アイコンで表現

---

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

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

### 推奨読解順序

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

未読メッセージの取得方法を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | getters.js | `app/javascript/widget/store/modules/conversation/getters.js` | getUnreadTextMessages getter |

**読解のコツ**: getUnreadTextMessagesはconversationsからテキストメッセージのみをフィルタリングして返す。

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

ルーティングとビューコンポーネントの構成を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | router.js | `app/javascript/widget/router.js` | L9-12: unread-messagesルート定義 |
| 2-2 | UnreadMessages.vue | `app/javascript/widget/views/UnreadMessages.vue` | ビューコンポーネント |

**主要処理フロー**:
1. **L12-14**: mapGettersでmessages取得（getUnreadTextMessages）
2. **L17-21**: closeFullViewメソッド - ウィジェット閉じる

#### Step 3: サブコンポーネントを理解する

未読メッセージ表示のコンポーネントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | UnreadMessageList.vue | `app/javascript/widget/components/UnreadMessageList.vue` | メッセージリスト表示 |
| 3-2 | UnreadMessage.vue | `app/javascript/widget/components/UnreadMessage.vue` | 個別メッセージ表示 |

**UnreadMessageList.vue主要処理**:
- **L29-31**: sender計算 - 最初のメッセージから送信者取得
- **L38-39**: openConversationView - 会話画面遷移イベント発火
- **L44-52**: getMessageContent - 添付ファイル判定

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

```
UnreadMessages.vue (ビュー)
    |
    +-- UnreadMessageList.vue
            |
            +-- 閉じるボタン
            |       |
            |       +-- @click -> closeFullView() [emit('close')]
            |               |
            |               +-- UnreadMessages.vue: closeFullView()
            |                       |
            |                       +-- IFrameHelper.sendMessage({ event: 'toggleBubble' })
            |
            +-- UnreadMessage.vue (各メッセージ)
            |       |
            |       +-- 送信者アバター、メッセージ内容
            |
            +-- View Messages ボタン
                    |
                    +-- @click -> openConversationView()
                            |
                            +-- emitter.emit(ON_UNREAD_MESSAGE_CLICK)
```

### データフロー図

```
[ストア]                  [コンポーネント]              [出力]

conversation/getUnreadTextMessages
        |
        v
UnreadMessages.vue ---> messages prop
        |
        v
UnreadMessageList.vue ---> 表示
        |
        +-- closeFullView() -------> IFrameHelper.sendMessage()
        |                                   |
        |                                   v
        |                            親ページ（toggleBubble）
        |
        +-- openConversationView() -> emitter.emit()
                                            |
                                            v
                                    ON_UNREAD_MESSAGE_CLICK
                                            |
                                            v
                                    メッセージ画面へ遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UnreadMessages.vue | `app/javascript/widget/views/UnreadMessages.vue` | ソース | ビューコンポーネント |
| UnreadMessageList.vue | `app/javascript/widget/components/UnreadMessageList.vue` | ソース | メッセージリスト |
| UnreadMessage.vue | `app/javascript/widget/components/UnreadMessage.vue` | ソース | 個別メッセージ |
| router.js | `app/javascript/widget/router.js` | ソース | ルーティング |
| getters.js | `app/javascript/widget/store/modules/conversation/getters.js` | ソース | 会話getter |
| utils.js | `app/javascript/widget/helpers/utils.js` | ソース | IFrameHelper |
| widgetBusEvents.js | `app/javascript/widget/constants/widgetBusEvents.js` | ソース | イベント定数 |
