# 画面設計書 20-カード編集画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおける「カード編集画面」の設計書です。カードのタイトルと説明を編集するためのインラインフォーム画面の仕様を定義します。

### 本画面の処理概要

本画面では、公開済みカードのタイトルと説明を編集します。カード詳細画面内でTurbo Frameを使用してインライン表示され、編集完了後は即座にカード詳細表示に戻ります。

**業務上の目的・背景**：タスクの内容は進捗に応じて変化することがあります。本画面では、カードのタイトルや詳細説明を素早く編集できるインターフェースを提供し、常に最新の情報を保持できるようにします。リッチテキストエディタにより、画像やリンクを含む詳細な説明を記述できます。

**画面へのアクセス方法**：カード詳細画面でタイトルまたは説明エリアをクリックすると、Turbo Frameでこの編集画面がインライン読み込みされます。URLは `/cards/:id/edit` です。

**主要な操作・処理内容**：
1. カードタイトルの編集
2. カード説明の編集（リッチテキスト）
3. 変更の保存
4. 編集のキャンセル

**画面遷移**：
- 遷移元：カード詳細画面（インライン読み込み）
- 遷移先：カード詳細画面（保存/キャンセル後）

**権限による表示制御**：ボードへのアクセス権を持つユーザーが編集可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | カード編集 | 主機能 | カードのタイトル・説明・画像を編集 |

## 画面種別

編集画面（インラインフォーム）

## URL/ルーティング

| HTTP Method | URL | Controller#Action |
|-------------|-----|-------------------|
| GET | /cards/:id/edit | cards#edit |
| PATCH/PUT | /cards/:id | cards#update |

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | データ型 | 必須 | 最大長 | 説明 |
|--------|--------|-----------|----------|------|--------|------|
| タイトル | title | 入力 | String | 必須 | 255文字 | カードのタイトル |
| 説明 | description | 入力 | Rich Text | - | - | カードの詳細説明（リッチテキスト） |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| タイトル入力 | テキストエリア | 自動リサイズ対応、1行表示 |
| 説明入力 | リッチテキストエディタ | Lexxyエディタによるリッチテキスト入力 |
| 保存ボタン | ボタン | 「Save changes」（フッターに表示） |
| キャンセルリンク | 隠しリンク | ESCキーまたはフォーカス外れで発動 |

## イベント仕様

### 1-フォーム送信（保存）

**トリガー**:
- 「Save changes」ボタンクリック
- Ctrl+Enter / Cmd+Enter キー押下

**処理内容**:
1. フォームデータをPATCH /cards/:id に送信
2. Card#update!でタイトル・説明を更新
3. Turbo Streamsでカード詳細表示を更新
4. ローカルストレージの下書きデータをクリア

**事後処理**:
- Turbo Streamsでeditフレームを閉じ、表示モードに戻る
- クロージャボタンエリアが「Save changes」から元のボタンに戻る

### 2-キャンセル

**トリガー**:
- ESCキー押下
- キャンセルリンククリック

**処理内容**:
- 編集内容を破棄
- カード詳細表示に戻る

### 3-ローカル保存

**トリガー**:
- 入力内容変更時（lexxy:change）
- Turboナビゲーション時

**処理内容**:
- local-saveコントローラーによりローカルストレージに一時保存
- ブラウザクローズ時のデータ損失を防止

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存 | cards | UPDATE | タイトル・説明を更新 |
| 保存 | action_text_rich_texts | INSERT/UPDATE | 説明のリッチテキスト保存 |

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

#### cards

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | title | フォーム入力値 | カードタイトル |
| UPDATE | updated_at | 現在日時 | 更新日時 |
| UPDATE | last_active_at | 現在日時 | 最終アクティブ日時 |

#### action_text_rich_texts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | body | フォーム入力値 | リッチテキスト本文 |
| INSERT/UPDATE | name | "description" | リッチテキスト種別 |
| INSERT/UPDATE | record_type | "Card" | 関連モデルタイプ |
| INSERT/UPDATE | record_id | カードID | 関連カードID |

## メッセージ仕様

なし（インラインフォームのため、視覚的なフィードバックのみ）

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|----------|----------|
| バリデーションエラー | タイトルが空欄 | エラー表示（required属性によるブラウザバリデーション） |
| レコード不存在 | 存在しないカード番号でアクセス | HTTPステータス404を返却 |
| アクセス権なし | ボードへのアクセス権がない | HTTPステータス404を返却 |
| 認証エラー | 未ログイン状態でアクセス | ログイン画面にリダイレクト |

## 備考

- 編集フォームはTurbo Frame内でインライン表示されます
- タイトル入力フィールドは自動リサイズ（autoresize）に対応しています
- 説明入力はLexxy（カスタムリッチテキストエディタ）を使用しています
- ローカルストレージへの自動保存（local-save）により、編集中のデータ損失を防止しています
- 編集モード時、フッターのボタンが「Save changes」に切り替わります
- 一般的なプロンプト（@メンション等）が説明エディタ内で利用可能です

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | card.rb | `app/models/card.rb` | has_rich_text :description の定義を確認 |
| 1-2 | schema.rb | `db/schema.rb` | cardsテーブル（title カラム）、action_text_rich_texts テーブルを確認 |

**読解のコツ**: Action TextによるRich Text実装を理解することが重要です。descriptionはaction_text_rich_textsテーブルに保存されます。

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

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

**主要処理フロー**:
1. **30-31行目**: `edit`アクション - カード編集フォーム表示
2. **33-39行目**: `update`アクション - カード情報更新
3. **68-69行目**: `card_params` - title, description等を許可

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.html.erb | `app/views/cards/edit.html.erb` | Turbo Frame構造、turbo_stream.update、フォーム構造を確認 |

**主要処理フロー**:
- **1行目**: `turbo_frame_tag @card, :edit` でフレーム定義
- **5-7行目**: `turbo_stream.update` でクロージャボタンを保存ボタンに置換
- **9-27行目**: フォーム構造（form_with）
- **12-16行目**: タイトル入力（text_area + autoresize）
- **19-23行目**: 説明入力（rich_textarea + local-save）

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

```
カード詳細画面（タイトル/説明クリック）
    │
    └─ GET /cards/:id/edit（Turbo Frame）
           │
           ├─ CardsController#edit
           │      └─ set_card（before_action）
           │
           └─ app/views/cards/edit.html.erb
                  ├─ turbo_frame_tag @card, :edit
                  ├─ turbo_stream.update（保存ボタン表示）
                  └─ form_with
                         ├─ text_area :title（autoresize）
                         └─ rich_textarea :description（local-save）

フォーム送信
    │
    └─ PATCH /cards/:id
           │
           ├─ CardsController#update
           │      ├─ @card.update!(card_params)
           │      └─ respond_to（turbo_stream/json）
           │
           └─ Turbo Streams応答
                  └─ editフレームを閉じ、表示モードに戻る
```

### データフロー図

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

タイトル ─────────────▶ CardsController#update ─────▶ cards テーブル
説明（Rich Text） ────▶          │                        │
                                 │                        ▼
                                 │                   action_text_rich_texts
                                 │
                                 └─ turbo_stream ──────▶ カード詳細表示
                                        │              （インライン更新）
                                        │
                                        └─ local-save ─▶ ローカルストレージ
                                             クリア
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| edit.html.erb | `app/views/cards/edit.html.erb` | テンプレート | カード編集フォーム |
| _save_button.html.erb | `app/views/cards/container/_save_button.html.erb` | パーシャル | 保存ボタン表示 |
| cards_controller.rb | `app/controllers/cards_controller.rb` | コントローラー | edit/updateアクション |
| card.rb | `app/models/card.rb` | モデル | カードモデル（has_rich_text :description） |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| autoresize_controller.js | `app/javascript/controllers/autoresize_controller.js` | Stimulusコントローラー | テキストエリア自動リサイズ |
| local_save_controller.js | `app/javascript/controllers/local_save_controller.js` | Stimulusコントローラー | ローカルストレージ保存 |
