# 画面設計書 27-カードウォッチ画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるカードウォッチ画面の設計を記述したものです。カードウォッチ画面は、カードのウォッチ状態を表示するTurbo Frameコンポーネントです。

### 本画面の処理概要

**業務上の目的・背景**：チームでタスク管理を行う際、自分が直接担当していなくても、特定のカードの進捗や更新を把握したいケースがあります。ウォッチ機能により、カードの更新通知を受け取るよう設定でき、重要なタスクの状況を見逃さずに追跡できます。この画面はウォッチ状態の表示と、ウォッチ/解除ボタンを提供します。

**画面へのアクセス方法**：カード詳細画面のウォッチボタンエリアに表示されます。URLは `/cards/:card_id/watch` ですが、通常はTurbo Frameとしてカード詳細画面に埋め込まれます。

**主要な操作・処理内容**：
1. 現在のウォッチ状態の表示（ウォッチ中/未ウォッチ）
2. ウォッチ開始操作（ショートカットキー `Shift+N`）
3. ウォッチ解除操作

**画面遷移**：
- 遷移元：カード詳細画面（インライン表示）
- 遷移先：なし（Turbo Streamで画面更新）

**権限による表示制御**：ログインユーザーのみアクセス可能です。ウォッチは個人単位で管理され、他のユーザーのウォッチ状態には影響しません。コメントを投稿すると自動的にウォッチ状態になります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | カードをウォッチ | 主機能 | カードのウォッチ状態を表示 |
| 36 | カードのウォッチ解除 | 補助機能 | ウォッチを解除 |

## 画面種別

状態表示/操作（インライン）

## URL/ルーティング

| HTTPメソッド | URL | コントローラー#アクション |
|-------------|-----|------------------------|
| GET | `/cards/:card_id/watch` | `cards/watches#show` |
| POST | `/cards/:card_id/watch` | `cards/watches#create` |
| DELETE | `/cards/:card_id/watch` | `cards/watches#destroy` |

## 入出力項目

本画面に入力項目はありません。操作はボタンクリックのみです。

## 表示項目

| 項目名 | データソース | 説明 |
|-------|-------------|------|
| ウォッチボタン | card.watched_by?(Current.user) | ウォッチ状態に応じてアイコンと動作が切り替わる |
| ツールチップ | 固定文字列 | 「Watch this」または「Stop watching」 |
| ショートカットキー | 固定文字列 | shift+n |

## イベント仕様

### 1-ウォッチボタンクリック（未ウォッチ時）

ウォッチしていないカードでボタンをクリックすると、カードがウォッチ状態になります。

**処理内容**：
1. `card_watch_path`へPOSTリクエスト送信
2. `@card.watch_by(Current.user)`でウォッチを作成/更新
3. Turbo Streamで応答

### 2-ウォッチ解除ボタンクリック（ウォッチ中時）

ウォッチ中のカードでボタンをクリックすると、ウォッチが解除されます。

**処理内容**：
1. `card_watch_path`へDELETEリクエスト送信
2. `@card.unwatch_by(Current.user)`でウォッチを解除
3. Turbo Streamで応答

### 3-ショートカットキー（Shift+N）

`Shift+N`キーを押すと、現在表示しているカードのウォッチ状態がトグルされます。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | watches | SELECT | ユーザーのウォッチ状態を取得 |
| ウォッチ開始 | watches | INSERT/UPDATE | ウォッチレコードの作成または更新 |
| ウォッチ解除 | watches | UPDATE | watchingフラグをfalseに更新 |
| ウォッチ状態変更 | cards | UPDATE | updated_atの更新（touch） |

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

#### watches

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | card_id, user_id | ウォッチ状態の確認 |
| INSERT | account_id | user.account_id | 自動設定 |
| INSERT | card_id | @card.id | 対象カード |
| INSERT | user_id | Current.user.id | ウォッチしたユーザー |
| INSERT | watching | true | ウォッチ状態フラグ |
| UPDATE | watching | false | ウォッチ解除時 |

#### cards

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | updated_at | 現在時刻 | watches belongs_to :card, touch: true |

## メッセージ仕様

本画面では明示的なメッセージ表示はありません。ウォッチ状態の変更は即座にアイコンに反映されます。

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| カードが存在しない | 404エラーページを表示 |
| カードへのアクセス権限がない | 404エラーページを表示 |

## 備考

- Turbo Frameで読み込まれ、`turbo_frame_tag @card, :watch`でフレームを識別します
- ETTagによるキャッシュ制御が実装されています（`fresh_when etag: @card.watch_for(Current.user) || "none"`）
- ウォッチはレコードを削除するのではなく、`watching`フラグで管理されます（watchingスコープ、not_watchingスコープ）
- `hotkey`コントローラーでショートカットキー（Shift+N）が実装されています
- `tooltip`コントローラーでホバー時にツールチップが表示されます
- ウォッチ中はボタンに`btn--reversed`クラスが適用され、視覚的に区別されます
- カードにコメントを投稿すると、自動的にそのカードをウォッチするようになります（Commentモデルの`after_create_commit :watch_card_by_creator`）

---

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

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

### 推奨読解順序

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

まず、ウォッチ機能に関連するモデル構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | watch.rb | `app/models/watch.rb` | Watchモデル、watchingスコープ、belongs_to |
| 1-2 | schema.rb | `db/schema.rb` | watchesテーブル（791-802行目） |

**読解のコツ**: Watchモデルはwatchingブーリアンフラグで状態を管理します。削除ではなく、フラグの更新で解除を表現しています。

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

処理の起点となるコントローラーを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | watches_controller.rb | `app/controllers/cards/watches_controller.rb` | show/create/destroyアクションの処理 |
| 2-2 | card_scoped.rb | `app/controllers/concerns/card_scoped.rb` | CardScopedモジュール |

**主要処理フロー**:
1. **4-6行目**: `show` - ETTagでウォッチ状態をキャッシュ
2. **8-14行目**: `create` - `watch_by`でウォッチ開始
3. **16-24行目**: `destroy` - `unwatch_by`でウォッチ解除

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

画面の表示内容を構成するビューファイルを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.erb | `app/views/cards/watches/show.html.erb` | Turbo Frame定義 |
| 3-2 | _watch_button.html.erb | `app/views/cards/watches/_watch_button.html.erb` | ウォッチボタンのUI |

**主要処理フロー**:
- **1行目**: `turbo_frame_tag @card, :watch` - Turbo Frameの定義
- **2行目**: パーシャルをレンダリング
- パーシャル内でウォッチ状態に応じて異なるボタンを表示

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

```
GET /cards/:card_id/watch
    |
    +-- Cards::WatchesController#show
           |
           +-- CardScoped#set_card (before_action)
           |      +-- Current.user.accessible_cards.find_by!
           |
           +-- fresh_when etag: @card.watch_for(Current.user)
           |
           +-- render 'cards/watches/show'
                  +-- render 'cards/watches/_watch_button'

POST /cards/:card_id/watch
    |
    +-- Cards::WatchesController#create
           |
           +-- @card.watch_by(Current.user)
           |
           +-- respond_to turbo_stream / json

DELETE /cards/:card_id/watch
    |
    +-- Cards::WatchesController#destroy
           |
           +-- @card.unwatch_by(Current.user)
           |
           +-- respond_to turbo_stream / json
```

### データフロー図

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

ボタン操作               WatchesController                 Turbo Stream
    |                         |
    +-- POST ────────────▶ create ─────────────────────▶ watches INSERT/UPDATE
    |                         +-- watch_by                  watching = true
    |
    +-- DELETE ──────────▶ destroy ────────────────────▶ watches UPDATE
                              +-- unwatch_by                watching = false
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| watches_controller.rb | `app/controllers/cards/watches_controller.rb` | ソース | ウォッチ機能コントローラー |
| card_scoped.rb | `app/controllers/concerns/card_scoped.rb` | ソース | カード取得の共通処理 |
| show.html.erb | `app/views/cards/watches/show.html.erb` | テンプレート | ウォッチ状態表示のTurbo Frame |
| _watch_button.html.erb | `app/views/cards/watches/_watch_button.html.erb` | テンプレート | ウォッチボタンパーシャル |
| watch.rb | `app/models/watch.rb` | ソース | Watchモデル |
| comment.rb | `app/models/comment.rb` | ソース | コメント作成時の自動ウォッチ |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | 設定 | データベーススキーマ |
