# 画面設計書 36-コレクション作成画面

## 概要

本ドキュメントは、Medusa Admin Dashboard におけるコレクション作成画面の設計を記述したものです。

### 本画面の処理概要

新しい商品コレクションを作成するための画面です。コレクションのタイトルとハンドル（URL識別子）を入力して、新規コレクションを登録します。

**業務上の目的・背景**：ECサイトの運営において、商品を特定のテーマやキャンペーンでグルーピングする必要があります。「夏のセール」「新着商品」「おすすめ商品」など、マーケティング施策や季節に応じた商品コレクションを作成することで、顧客に効果的な商品提案が可能になります。シンプルな入力フィールドで素早くコレクションを作成できるため、運用負荷を最小限に抑えられます。

**画面へのアクセス方法**：コレクション一覧画面の「作成」ボタン押下で、フルスクリーンモーダル形式で表示されます。

**主要な操作・処理内容**：
1. タイトルの入力 - コレクション名（必須）
2. ハンドルの入力 - URL識別子（任意、未入力時は自動生成）
3. 作成ボタン押下で新規コレクションを登録

**画面遷移**：コレクション一覧画面から遷移してきます。作成完了後は作成したコレクションの詳細画面へ遷移します。キャンセル時はコレクション一覧画面に戻ります。

**権限による表示制御**：管理者権限を持つユーザーのみがコレクションを作成できます。認証されていないユーザーはログイン画面にリダイレクトされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 商品コレクション管理 | 主機能 | 新規コレクションの作成 |

## 画面種別

作成（フルスクリーンモーダル形式）

## URL/ルーティング

`/collections/create`

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 最大長 | 入力/出力 | 説明 |
|--------|--------|-----|------|--------|-----------|------|
| タイトル | title | string | 必須 | - | 入力 | コレクション名（最低1文字） |
| ハンドル | handle | string | 任意 | - | 入力 | URL識別子（未入力時は自動生成） |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ヘッダー | モーダルヘッダー | 標準のフルスクリーンモーダルヘッダー |
| 画面タイトル | Heading | "Create Collection"（i18n: collections.createCollection） |
| 説明テキスト | Text | コレクション作成の説明（i18n: collections.createCollectionHint） |
| タイトルラベル | フォームラベル | "Title"（i18n: fields.title） |
| ハンドルラベル | フォームラベル（tooltip付き、optional表示） | "Handle"（i18n: fields.handle） |
| キャンセルボタン | Button | "Cancel"（i18n: actions.cancel） |
| 作成ボタン | Button | "Create"（i18n: actions.create） |

## イベント仕様

### 1-作成ボタン押下

フォームのバリデーションを実行し、成功した場合はAPIを呼び出して新規コレクションを作成します。

**処理フロー**:
1. Zodスキーマによるバリデーション実行（titleは必須、handleは任意）
2. `useCreateCollection` フックを使用してAPI呼び出し
3. 成功時: トースト通知（collections.createSuccess）を表示し、詳細画面へ遷移
4. 失敗時: エラーメッセージをトーストで表示

**API呼び出し**:
- エンドポイント: `POST /admin/collections`
- リクエストボディ:
  ```json
  {
    "title": "string",
    "handle": "string"  // 任意
  }
  ```

### 2-キャンセルボタン押下

フォームの入力を破棄し、モーダルを閉じてコレクション一覧画面に戻ります。

### 3-ハンドル入力

HandleInputコンポーネントを使用し、スラッシュ(/)のプレフィックスなしでハンドルを入力できます。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 作成ボタン押下 | product_collection | INSERT | 新規コレクションを作成 |

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

#### product_collection

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | UUID自動生成 | コレクションID |
| INSERT | title | フォーム入力値 | コレクション名 |
| INSERT | handle | フォーム入力値または自動生成 | URL識別子 |
| INSERT | created_at | 現在日時 | 自動設定 |
| INSERT | updated_at | 現在日時 | 自動設定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|------------|------|--------------|--------------|
| collections.createSuccess | 成功 | コレクションが正常に作成されました | 作成成功時 |
| - | エラー | {error.message} | API呼び出し失敗時 |
| - | バリデーションエラー | フィールド別エラーメッセージ | 入力値不正時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| API通信エラー | トーストでエラーメッセージを表示 |
| バリデーションエラー | 各フィールドの下にエラーメッセージを表示 |
| ハンドル重複 | APIエラーとしてトーストで表示 |
| 認証エラー | ログイン画面にリダイレクト |

## 備考

- フルスクリーンモーダル形式（RouteFocusModal）で表示
- キーボードショートカット対応（KeyboundForm）
- フォームの状態管理にはreact-hook-formを使用
- バリデーションにはZodスキーマを使用
- handleフィールドはoptional（任意）表示
- handleフィールドにはtooltipでヒントを表示（collections.handleTooltip）
- HandleInputコンポーネントで自動的にスラッシュ処理

---

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

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

### 推奨読解順序

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

フォームのスキーマを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | create-collection-form.tsx | `packages/admin/dashboard/src/routes/collections/collection-create/components/create-collection-form/create-collection-form.tsx` | CreateCollectionSchema（16-19行目）でフォームのバリデーションルールを確認 |

**読解のコツ**: titleは`z.string().min(1)`で必須、handleは`z.string().optional()`で任意です。

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

ルートコンポーネントから画面がどのように構成されるかを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | collection-create.tsx | `packages/admin/dashboard/src/routes/collections/collection-create/collection-create.tsx` | RouteFocusModalでフルスクリーン表示、CreateCollectionFormを子コンポーネントとして配置 |

**主要処理フロー**:
1. **4行目**: RouteFocusModalでフルスクリーンモーダルを表示
2. **7行目**: CreateCollectionFormコンポーネントを配置

#### Step 3: フォームコンポーネントを理解する

作成フォームの実装詳細を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create-collection-form.tsx | `packages/admin/dashboard/src/routes/collections/collection-create/components/create-collection-form/create-collection-form.tsx` | useForm、useCreateCollection、handleSubmitの実装を確認 |

**主要処理フロー**:
- **25-31行目**: useFormでフォーム初期化、空文字をデフォルト値に設定
- **33行目**: useCreateCollectionでミューテーションフック取得
- **35-45行目**: handleSubmitで送信処理を定義
- **37-44行目**: mutateAsyncでAPI呼び出し、成功時は詳細画面へ遷移
- **63-77行目**: titleフィールドの定義
- **78-97行目**: handleフィールドの定義（optional、tooltip付き）

#### Step 4: APIフックを理解する

バックエンドとの通信処理を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | collections.tsx | `packages/admin/dashboard/src/hooks/api/collections.tsx` | useCreateCollection（142-158行目）の実装を確認 |

**主要処理フロー**:
- **150行目**: sdk.admin.productCollection.createでAPI呼び出し
- **151-153行目**: 成功時にクエリキャッシュを無効化

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

```
CollectionCreate (collection-create.tsx)
    │
    └─ RouteFocusModal
           │
           └─ CreateCollectionForm (create-collection-form.tsx)
                  │
                  ├─ useForm() → フォーム状態管理
                  │
                  ├─ useRouteModal() → モーダル制御
                  │      └─ handleSuccess() → 詳細画面へ遷移
                  │
                  ├─ useCreateCollection() → 作成ミューテーション
                  │      └─ sdk.admin.productCollection.create()
                  │
                  └─ handleSubmit() → フォーム送信処理
                         ├─ mutateAsync() → API呼び出し
                         ├─ toast.success() → 成功通知
                         └─ handleSuccess() → 遷移
```

### データフロー図

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

フォーム入力 ─────────▶ Zodバリデーション
(title, handle)               │
                              ▼
                        useCreateCollection
                              │
                              ▼
                        SDK API呼び出し ───▶ product_collection INSERT
                              │
                              ▼
                        クエリキャッシュ無効化
                              │
                              ▼
成功 ─────────────────▶ handleSuccess() ───▶ 詳細画面へ遷移
                              │               (/collections/:id)
失敗 ─────────────────▶ toast.error() ───▶ エラー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| collection-create.tsx | `packages/admin/dashboard/src/routes/collections/collection-create/collection-create.tsx` | ソース | ルートコンポーネント |
| create-collection-form.tsx | `packages/admin/dashboard/src/routes/collections/collection-create/components/create-collection-form/create-collection-form.tsx` | ソース | 作成フォームコンポーネント |
| index.ts | `packages/admin/dashboard/src/routes/collections/collection-create/index.ts` | ソース | エクスポート定義 |
| collections.tsx | `packages/admin/dashboard/src/hooks/api/collections.tsx` | ソース | コレクションAPI フック |
| RouteFocusModal | `packages/admin/dashboard/src/components/modals/` | ソース | フルスクリーンモーダル |
| Form | `packages/admin/dashboard/src/components/common/form/` | ソース | フォームコンポーネント |
| HandleInput | `packages/admin/dashboard/src/components/inputs/handle-input/` | ソース | ハンドル入力コンポーネント |
| KeyboundForm | `packages/admin/dashboard/src/components/utilities/keybound-form/` | ソース | キーバインド対応フォーム |
