# 画面設計書 49-ピン一覧画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるピン一覧画面の設計仕様を定義したものです。ユーザーがピン留めしたカードの一覧を表示する画面について記載しています。

### 本画面の処理概要

本画面は、ユーザーが自分でピン留めしたカードの一覧を表示する画面です。よく参照するカードやすぐにアクセスしたいカードをピン留めしておくことで、素早くアクセスできます。

**業務上の目的・背景**：タスク管理やプロジェクト管理において、特に重要なカードや頻繁に参照するカードを素早く見つけられることは作業効率に直結します。本画面は、ユーザーが「重要」と判断したカードを一覧で表示し、ワンクリックでアクセスできるようにすることで、作業効率の向上を支援します。

**画面へのアクセス方法**：マイメニュー画面（No.48）からピン留め一覧へのリンク、またはURLを直接入力してアクセスします。

**主要な操作・処理内容**：
1. ピン留めしたカードの一覧を表示する
2. カードをクリックしてカード詳細画面に遷移する
3. ピン留めを解除する

**画面遷移**：
- 遷移元：マイメニュー画面（No.48）/ ホーム画面（No.8）
- 遷移先：カード詳細画面（No.19）

**権限による表示制御**：認証済みユーザーのみアクセス可能です。自分のピン留めのみ表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 90 | ピン留め一覧表示 | 主機能 | ピン留めしたカードの一覧を表示 |

## 画面種別

一覧

## URL/ルーティング

- パス: `/my/pins`
- HTTPメソッド: GET
- ルート名: `my_pins_path`
- コントローラ: `My::PinsController#index`

## 入出力項目

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

## 表示項目

| 項目名 | 説明 | 表示条件 |
|--------|------|----------|
| ページタイトル | "Pinned" | 常時 |
| 戻るリンク | "Home" | 常時 |
| ピン留めカード一覧 | ピン留めしたカードのプレビュー | 常時 |
| ピン解除ボタン | 各カードのピン留めを解除 | 各カードに表示 |

## イベント仕様

### 1-戻るリンク押下

ヘッダーの「Home」リンクをクリックすると、ホーム画面（`root_path`）に遷移します。キーボードショートカット（左矢印キー、Escキー）でも同様の動作が可能です。

### 2-カードプレビュー押下

カードのプレビューをクリックすると、カード詳細画面に遷移します。

### 3-ピン解除ボタン押下

各カードのピンアイコンボタンをクリックすると、DELETEリクエストが送信され、ピン留めが解除されます。解除後、そのカードは一覧から削除されます。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | pins | SELECT | ユーザーのピン一覧を取得 |
| 画面表示 | cards | SELECT | ピン留めされたカードを取得 |
| ピン解除ボタン押下 | pins | DELETE | ピン留めを削除 |

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

#### pins（ピン解除時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | card_id, user_id | 該当するピン留めを削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | スクリーンリーダー | Unpin this card | ピン解除ボタンのラベル |

## 例外処理

| 例外ケース | 対応 |
|-----------|------|
| 認証されていない | ログイン画面へリダイレクト |
| ピン留めが0件 | 空の一覧が表示される |

## 備考

- Turbo Frame `pins` を使用してピン一覧を表示
- `fresh_when` によるHTTPキャッシュが適用されている
- ピン一覧は作成日時の降順（`ordered`スコープ）で表示される
- Web表示では最大20件、JSON APIでは最大100件のピンが返される
- 各ピンは `cards/display/preview` パーシャルでカードプレビューを表示
- ピン解除はDELETEリクエストで `card_pin_path` に送信される
- `navigable-list` によるキーボードナビゲーションが可能

---

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

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

### 推奨読解順序

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

ピン留めに関わるモデルの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pin.rb | `app/models/pin.rb` | Pinモデルの構造とorderedスコープを確認 |
| 1-2 | user.rb | `app/models/user.rb` | UserとPinの関連を確認 |
| 1-3 | card.rb | `app/models/card.rb` | PinとCardの関連を確認（存在する場合） |

**読解のコツ**: Pinモデルはuser_idとcard_idを持ち、ユーザーとカードの中間テーブルとして機能します。`ordered`スコープで作成日時の降順にソートされます。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pins_controller.rb | `app/controllers/my/pins_controller.rb` | indexアクションとデータ取得ロジックを確認 |

**主要処理フロー**:
1. **行3**: `@pins = user_pins` - ユーザーのピン一覧を取得
2. **行4**: `fresh_when` - HTTPキャッシュの設定
3. **行8-10**: `user_pins` - ピンとカードをincludesで取得、件数制限
4. **行12-14**: `pins_limit` - Web表示は20件、JSONは100件

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.erb | `app/views/my/pins/index.html.erb` | 一覧表示の構造を確認 |
| 3-2 | _pin.html.erb | `app/views/my/pins/_pin.html.erb` | 個別ピンの表示とピン解除ボタンを確認 |

**主要処理フロー**:
- **index.html.erb 行12-14**: Turbo Frame `pins` 内でピン一覧をレンダリング
- **_pin.html.erb 行2**: カードプレビューの表示
- **_pin.html.erb 行3-5**: ピン解除ボタン（DELETEメソッド）

#### Step 4: カードプレビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | _preview.html.erb | `app/views/cards/display/_preview.html.erb` | カードプレビューの表示内容を確認 |

**主要処理フロー**:
- カードのタイトル、ボード名、ステータスなどを表示

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

```
My::PinsController#index
    │
    ├─ user_pins
    │      │
    │      ├─ Current.user.pins
    │      │
    │      ├─ includes(:card)
    │      │
    │      ├─ ordered（created_at: :desc）
    │      │
    │      └─ limit(pins_limit)
    │             │
    │             └─ Web: 20 / JSON: 100
    │
    └─ index.html.erb レンダリング
           │
           ├─ turbo_frame_tag "pins"
           │
           └─ render partial: "my/pins/pin", collection: @pins
                  │
                  ├─ cards/display/preview パーシャル
                  │
                  └─ ピン解除ボタン
                         └─ button_to card_pin_path(pin.card), method: :delete
```

### データフロー図

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

なし                  PinsController#index               index.html.erb
    ───────────▶           │
                           ├─▶ Current.user.pins
                           │      └─▶ includes(:card)
                           │
                           ├─▶ ordered (created_at: :desc)
                           │
                           └─▶ limit(20)
                                     │
                                     └─▶ _pin.html.erb × N
                                            │
                                            └─▶ cards/display/preview
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pins_controller.rb | `app/controllers/my/pins_controller.rb` | コントローラ | データ取得・画面制御 |
| index.html.erb | `app/views/my/pins/index.html.erb` | ビュー | ピン一覧画面 |
| _pin.html.erb | `app/views/my/pins/_pin.html.erb` | パーシャル | 個別ピンの表示 |
| _preview.html.erb | `app/views/cards/display/_preview.html.erb` | パーシャル | カードプレビュー |
| pin.rb | `app/models/pin.rb` | モデル | ピンエンティティ |
| user.rb | `app/models/user.rb` | モデル | ユーザーエンティティ |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（行177） |
