# 画面設計書 60-リアクション一覧画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるリアクション一覧画面の設計仕様を記述したものである。

### 本画面の処理概要

本画面は、カードまたはコメントに付けられたリアクション（絵文字やテキスト）を一覧表示し、新しいリアクションを追加できるようにする画面である。Turbo Frameを使用してカード詳細画面の一部として動的に表示される。

**業務上の目的・背景**：チームメンバー間のコミュニケーションを促進するため、カードやコメントに対して絵文字やテキストでリアクションできる機能を提供している。本画面ではリアクションの一覧表示、追加ボタン、自分のリアクションの削除機能を提供する。ポジティブなフィードバックや感情表現を手軽に行うことで、チームのエンゲージメントを高める。

**画面へのアクセス方法**：カード詳細画面やコメント詳細画面のリアクションエリアに自動的に表示される。Turbo Frameで非同期に読み込まれる。URLパス `/cards/:card_id/reactions` に直接アクセスすることも可能。

**主要な操作・処理内容**：
1. 既存のリアクションを確認する
2. リアクション追加ボタンをクリックして新しいリアクションを追加する
3. 自分のリアクションをクリックして削除する

**画面遷移**：カード詳細画面またはコメント詳細画面から埋め込み表示される。リアクション追加ボタンでリアクション追加画面（new）に遷移する。

**権限による表示制御**：ログイン済みユーザーであればリアクションの追加・閲覧が可能。リアクションの削除は、そのリアクションを作成した本人のみが可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 49 | カードにリアクション | 主機能 | リアクションの一覧を表示 |

## 画面種別

一覧（埋め込み）

## URL/ルーティング

| メソッド | パス | アクション |
|---------|------|-----------|
| GET | /cards/:card_id/reactions | index（リアクション一覧表示） |
| GET | /cards/:card_id/comments/:comment_id/reactions | index（コメントのリアクション一覧） |

## 入出力項目

本画面には入力項目はない（表示と操作のみ）。

## 表示項目

| 項目名 | 説明 |
|--------|------|
| リアクション一覧 | 各リアクションをアバターとコンテンツで表示 |
| 追加ボタン | boost-color.svgアイコン - リアクション追加画面へ遷移 |

## イベント仕様

### 1-リアクション追加ボタン押下

リアクション追加画面（new）に遷移する。

1. link_toでnewアクションにリクエスト
2. Turbo Frameでリアクション追加フォームが表示される
3. soft-keyboardコントローラでモバイルキーボードを開く

### 2-リアクションコンテンツクリック（自分のリアクション）

リアクション削除UIを表示する。

1. reaction-deleteコントローラのrevealアクションが発火
2. 削除ボタンが表示される
3. 削除ボタンをクリックするとDELETEリクエストが送信される

### 3-削除ボタン押下

リアクションを削除する。

1. button_toでDELETEリクエストを送信
2. リアクションが削除される
3. Turbo Streamでリアクション一覧が更新される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | reactions | SELECT | リアクション一覧を取得 |
| 削除ボタン押下 | reactions | DELETE | リアクションを削除 |

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

#### reactions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | reactable_id, reactable_type | 対象カードまたはコメント | ポリモーフィック関連 |
| SELECT | - | ordered | 作成日時順で取得 |
| DELETE | id | params[:id] | 本人のリアクションのみ削除可 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| - | - | 特にメッセージ表示なし |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 未ログイン | ログイン画面にリダイレクト |
| 他人のリアクション削除を試行 | 403 Forbidden |
| 存在しないリアクションID | RecordNotFound例外 |

## 備考

- Turbo Frameを使用した非同期読み込み
- リアクションはポリモーフィック関連（Card, Comment両方に対応）
- reaction-deleteコントローラで削除UI制御
- 絵文字のみの場合はtxt-mediumスタイル、それ以外はtxt-small
- リアクション作成時にカードのlast_active_atを更新

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reaction.rb | `app/models/reaction.rb` | リアクションモデル、ポリモーフィック関連、all_emoji?判定 |

**読解のコツ**: `belongs_to :reactable, polymorphic: true`でカードとコメント両方に対応。`belongs_to :reacter`でリアクション作成者を保持。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reactions_controller.rb | `app/controllers/cards/reactions_controller.rb` | indexアクションの実装 |

**主要処理フロー**:
1. **3行目**: CardScopedインクルードで@cardを設定
2. **5行目**: set_reactableで@reactable = @card
3. **11-12行目**: indexアクション - "reactions/index"をrender
4. **28-32行目**: destroyアクション - 本人確認後に削除

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.erb | `app/views/reactions/index.html.erb` | _reactionsパーシャルを呼び出し |
| 3-2 | _reactions.html.erb | `app/views/reactions/_reactions.html.erb` | リアクション一覧表示、追加ボタン |
| 3-3 | _reaction.html.erb | `app/views/reactions/_reaction.html.erb` | 個別リアクション表示、削除UI |

**主要処理フロー**:
- **_reactions.html.erb 1行目**: turbo_frame_tagで非同期更新対応
- **3-5行目**: reactions__listにリアクションをrender
- **7-14行目**: 追加ボタン（newアクションへのリンク）
- **_reaction.html.erb 3-9行目**: reaction-deleteコントローラ設定
- **10-12行目**: アバター表示
- **14-16行目**: リアクションコンテンツ（クリックで削除UI表示）
- **18-24行目**: 削除ボタン（本人のみ表示）

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

```
カード詳細画面
    │
    └─ Turbo Frame: reactions
           │
           └─ GET /cards/:card_id/reactions
                  └─ Cards::ReactionsController#index
                         └─ render "reactions/index"
                                └─ render "reactions/reactions"
                                       ├─ render "reactions/reaction" (each)
                                       └─ 追加ボタン → newアクションへ

削除時:
    │
    └─ DELETE /cards/:card_id/reactions/:id
           └─ Cards::ReactionsController#destroy
                  ├─ ensure_permission_to_administer_reaction
                  └─ @reaction.destroy
                         └─ render "reactions/destroy" (Turbo Stream)
```

### データフロー図

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

@reactable ──────────────▶ ReactionsController#index ────▶ reactions/index
(Card or Comment)                │                              │
                                 ▼                              ▼
                          @reactable.reactions            _reactions.html.erb
                          (SELECT ordered)                     │
                                                               ├─ リアクション一覧
                                                               └─ 追加ボタン

リアクションクリック ────▶ reaction-deleteコントローラ ──▶ 削除UI表示
       │
       ▼
削除ボタン押下 ─────────▶ ReactionsController#destroy ──▶ Turbo Stream更新
                                 │
                                 ▼
                          reactions DELETE
                          (本人確認後)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reactions_controller.rb | `app/controllers/cards/reactions_controller.rb` | コントローラ | カードのリアクション制御 |
| reaction.rb | `app/models/reaction.rb` | モデル | リアクションモデル |
| index.html.erb | `app/views/reactions/index.html.erb` | ビュー | リアクション一覧（ラッパー） |
| _reactions.html.erb | `app/views/reactions/_reactions.html.erb` | パーシャル | リアクション一覧本体 |
| _reaction.html.erb | `app/views/reactions/_reaction.html.erb` | パーシャル | 個別リアクション |
| new.html.erb | `app/views/reactions/new.html.erb` | ビュー | リアクション追加フォーム |
| reaction_delete_controller.js | `app/javascript/controllers/reaction_delete_controller.js` | Stimulus | 削除UI制御 |
| soft_keyboard_controller.js | `app/javascript/controllers/soft_keyboard_controller.js` | Stimulus | モバイルキーボード制御 |
