# 画面設計書 18-カード一覧画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおける「カード一覧画面」の設計書です。フィルター条件に基づいてカードの一覧をグリッド形式で表示する画面仕様を定義します。

### 本画面の処理概要

本画面では、ユーザーがアクセス可能なすべてのボードに跨るカードを一覧表示します。様々なフィルター条件（ボード、担当者、タグ、ステータス等）を組み合わせて絞り込むことができ、保存済みフィルターの利用も可能です。

**業務上の目的・背景**：複数のボードに分散するタスクを横断的に確認したい場合があります。例えば「自分にアサインされているすべてのカード」や「特定タグが付いたカード」など、ボードを跨いだ視点でタスクを把握することで、効率的な作業管理が可能になります。

**画面へのアクセス方法**：マイメニューやナビゲーションから「Cards」リンクをクリックしてアクセスします。URLは `/cards` です。フィルター条件はクエリパラメータで指定可能です。

**主要な操作・処理内容**：
1. カードのグリッド表示
2. フィルター条件の設定（ボード、担当者、作成者、タグ、ステータス等）
3. フィルターの保存・管理
4. カードのドラッグ＆ドロップ操作
5. カードクリックでカード詳細画面へ遷移
6. ページネーション（無限スクロール）

**画面遷移**：
- 遷移元：マイメニュー画面、ホーム画面、ボード詳細画面
- 遷移先：カード詳細画面、ボード設定画面（単一ボードフィルター時）

**権限による表示制御**：ユーザーがアクセス可能なボードのカードのみ表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | カード一覧表示 | 主機能 | フィルター条件に基づいてカードの一覧を表示 |
| 55 | フィルター作成・保存 | 補助機能 | カード一覧のフィルター条件を作成・保存 |
| 56 | フィルター削除 | 補助機能 | 保存したフィルターを削除 |

## 画面種別

一覧画面

## URL/ルーティング

| HTTP Method | URL | Controller#Action |
|-------------|-----|-------------------|
| GET | /cards | cards#index |

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | データ型 | 必須 | 最大長 | 説明 |
|--------|--------|-----------|----------|------|--------|------|
| ボードID配列 | board_ids[] | 入力 | Array | - | - | フィルター対象ボード |
| 担当者ID配列 | assignee_ids[] | 入力 | Array | - | - | フィルター対象担当者 |
| 作成者ID配列 | creator_ids[] | 入力 | Array | - | - | フィルター対象作成者 |
| タグID配列 | tag_ids[] | 入力 | Array | - | - | フィルター対象タグ |
| インデックス | index | 入力 | String | - | - | stalled/postponing_soon/closed等 |
| ソート | sort | 入力 | String | - | - | newest/oldest/latest |
| 全展開フラグ | expand_all | 入力 | Boolean | - | - | フィルターUI展開状態 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ページタイトル | H1見出し | 選択されたボードのラベル（複数ボード/単一ボード名） |
| フィルター設定UI | 展開可能パネル | 各種フィルター条件の設定 |
| ボード設定リンク | アイコンリンク | 単一ボードフィルター時のみ表示 |
| カード一覧 | グリッド | カードのプレビュー表示 |
| 空メッセージ | テキスト | 「No cards match this filter」を表示 |

### フィルター設定項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ボード選択 | チェックボックス群 | 対象ボードの選択 |
| 担当者選択 | チェックボックス群 | 担当者での絞り込み |
| 作成者選択 | チェックボックス群 | 作成者での絞り込み |
| タグ選択 | チェックボックス群 | タグでの絞り込み |
| ステータス選択 | ラジオボタン群 | stalled/postponing_soon/closed等 |
| ソート | ラジオボタン群 | newest/oldest/latest |
| フィルター管理 | ボタン群 | 保存・削除操作 |

## イベント仕様

### 1-フィルター適用

**トリガー**: フィルター条件変更

**処理内容**:
1. フィルターフォームを送信
2. クエリパラメータをURLに反映
3. cards#indexアクションを実行
4. Turbo Frameでカード一覧を更新

**事後処理**:
- URLがフィルター条件を反映して更新される（turbo_action: "advance"）
- カード一覧がフィルター結果に更新

### 2-カードクリック

**トリガー**: カードプレビューをクリック

**処理内容**:
- カード詳細画面（/cards/:number）に遷移

### 3-ページネーション

**トリガー**: 画面最下部へのスクロール（自動ページネーション）

**処理内容**:
- 次のページのカードを読み込み
- 既存のカード一覧に追加表示

### 4-フィルター保存

**トリガー**: フィルター保存ボタンクリック

**処理内容**:
- 現在のフィルター条件をFiltersレコードとして保存

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | cards | SELECT | フィルター条件に合致するカードを取得 |
| フィルター保存 | filters | INSERT | フィルター条件を保存 |
| フィルター削除 | filters | DELETE | 保存済みフィルターを削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| M001 | 情報 | No cards match this filter | フィルター結果が0件の場合 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|----------|----------|
| 認証エラー | 未ログイン状態でアクセス | ログイン画面にリダイレクト |
| 無効なフィルター値 | 不正なパラメータ | 無視して処理を継続 |

## 備考

- 画面はTurbo Framesでページキャッシュから除外されています（turbo_exempts_page_from_cache）
- フィルター設定UIは展開/折りたたみ可能です
- 単一ボードでフィルター時は、ボード設定へのリンクが表示されます
- リアルタイム更新用のブロードキャスト購読が設定されています
- カードは preloaded スコープで関連データを事前読み込みします

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | card.rb | `app/models/card.rb` | Cardモデル、スコープ（indexed_by, sorted_by, preloaded）を確認 |
| 1-2 | filter.rb | `app/models/filter.rb` | Filterモデル、フィルター条件の保存構造を確認 |

**読解のコツ**: FilterScopedモジュールがフィルター処理の中心です。@filter変数にフィルター条件が保持されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.rb | `config/routes.rb` | 76行目の `resources :cards` を確認 |
| 2-2 | cards_controller.rb | `app/controllers/cards_controller.rb` | indexアクション、FilterScopedのincludeを確認 |

**主要処理フロー**:
1. **9-11行目**: `index`アクション - フィルター条件でカードを取得、ページネーション
2. **10行目**: `@filter.cards` - FilterScopedで構築されたフィルター結果

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.erb | `app/views/cards/index.html.erb` | ページ構造、フィルターUI、カード一覧を確認 |
| 3-2 | _settings.html.erb | `app/views/filters/_settings.html.erb` | フィルター設定UIのパーシャル |
| 3-3 | _previews.html.erb | `app/views/cards/display/_previews.html.erb` | カードプレビューコレクション |

**主要処理フロー**:
- **1行目(index.html.erb)**: ページタイトルを選択ボードラベルから設定
- **2行目**: turbo_exempts_page_from_cacheでキャッシュ除外
- **4行目**: ブロードキャスト購読の設定
- **18行目**: フィルター設定UIのレンダリング
- **20-29行目**: turbo_frame_tagでカード一覧をフレーム化

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

```
ブラウザ（GET /cards）
    │
    ├─ CardsController#index
    │      ├─ FilterScoped（before_action）
    │      │      └─ @filter, @user_filtering の設定
    │      └─ set_page_and_extract_portion_from @filter.cards
    │
    └─ app/views/cards/index.html.erb
           ├─ render "cards/broadcasts"
           ├─ render "filters/settings"
           │      └─ フィルター条件入力UI
           └─ turbo_frame_tag :cards_container
                  ├─ with_automatic_pagination
                  │      └─ _previews.html.erb
                  └─ blank-slate（カードなしの場合）
```

### データフロー図

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

フィルターパラメータ
  ├─ board_ids ────────▶ FilterScoped ───────────▶ @filter
  ├─ assignee_ids ─────▶      │
  ├─ creator_ids ──────▶      │
  ├─ tag_ids ──────────▶      │
  ├─ index ────────────▶      │
  └─ sort ─────────────▶      │
                              │
                              └─ @filter.cards ───▶ @page.records
                                       │                  │
                                       │                  ▼
                                       └─ render ──▶ カードグリッド
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html.erb | `app/views/cards/index.html.erb` | テンプレート | カード一覧画面のメインビュー |
| _settings.html.erb | `app/views/filters/_settings.html.erb` | パーシャル | フィルター設定UI |
| _previews.html.erb | `app/views/cards/display/_previews.html.erb` | パーシャル | カードコレクション |
| _preview.html.erb | `app/views/cards/display/_preview.html.erb` | パーシャル | 個別カードプレビュー |
| cards_controller.rb | `app/controllers/cards_controller.rb` | コントローラー | indexアクションの実装 |
| card.rb | `app/models/card.rb` | モデル | カードモデル |
| filter.rb | `app/models/filter.rb` | モデル | フィルターモデル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
