# 画面設計書 125-販売チャネル作成画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおける販売チャネル作成画面の設計を記述したものです。新規販売チャネルを作成するためのモーダル形式のフルスクリーンフォーム画面です。

### 本画面の処理概要

この画面では、新規の販売チャネルを作成できます。販売チャネルの基本情報（名前、説明）と有効/無効状態を設定します。

**業務上の目的・背景**：ECサイト運営において、新しい販売経路（新規Webサイト、モバイルアプリ、マーケットプレイス連携など）を追加する際に、対応する販売チャネルを作成する必要があります。販売チャネルは商品の公開範囲を制御し、APIキーと連携してチャネル固有のアクセス制御を実現します。この画面は、そうした新規チャネルを簡単に追加するためのインターフェースを提供します。

**画面へのアクセス方法**：販売チャネル一覧画面（No.124）の「作成」ボタンをクリックしてアクセスします。URLパスは `/settings/sales-channels/create` です。RouteFocusModal形式（フルスクリーンモーダル）で表示されます。

**主要な操作・処理内容**：
1. 販売チャネル名の入力（必須）
2. 説明の入力（必須）
3. 有効/無効状態の設定（デフォルトは有効）
4. 保存ボタンクリックで販売チャネルを作成
5. キャンセルボタンクリックでモーダルを閉じる

**画面遷移**：
- 遷移元：販売チャネル一覧画面（No.124）
- 遷移先：作成完了後、作成された販売チャネルの詳細画面（No.126）へ遷移

**権限による表示制御**：認証済みの管理者ユーザーのみアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 70 | 販売チャネルCRUD | 主機能 | 新規販売チャネルの作成 |

## 画面種別

登録（モーダル形式）

## URL/ルーティング

`/settings/sales-channels/create`

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| name | 入力（フォーム） | string | Yes | 販売チャネル名（1文字以上） |
| description | 入力（フォーム） | string | Yes | 説明（1文字以上） |
| enabled | 入力（フォーム） | boolean | Yes | 有効/無効状態（デフォルト: true） |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| ヘッダータイトル | string | 「販売チャネルを作成」（i18n: salesChannels.createSalesChannel） |
| サブタイトル | string | 作成のヒントメッセージ（i18n: salesChannels.createSalesChannelHint） |
| 名前入力フィールド | Input | name入力欄 |
| 説明入力フィールド | Textarea | description入力欄 |
| 有効スイッチ | Switch | enabled切り替え |
| ヒントテキスト | string | 有効化の説明（i18n: salesChannels.enabledHint） |

## イベント仕様

### 1-保存ボタンクリック

保存ボタンをクリックすると、フォームのバリデーション後に販売チャネルが作成されます。

- バリデーション:
  - name: 必須、1文字以上の文字列
  - description: 必須、1文字以上の文字列
  - enabled: boolean（is_disabledに変換して送信）
- 処理内容:
  - `POST /admin/sales-channels` APIを呼び出し（useCreateSalesChannelフック）
  - リクエストボディ: `{ name, description, is_disabled: !enabled }`
  - 成功時: トースト通知を表示し、作成された販売チャネルの詳細画面へ遷移
  - 失敗時: エラーメッセージをトースト通知で表示

### 2-キャンセルボタンクリック

キャンセルボタンをクリックすると、入力内容を破棄してモーダルを閉じます。

- 処理内容: RouteFocusModal.Closeによりモーダルを閉じる

### 3-フォーム入力

キーボードショートカット（KeyboundForm）により、Enterキーでフォーム送信が可能です。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | sales_channel | INSERT | 新規販売チャネルの作成 |

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

#### sales_channel

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成 | UUID |
| INSERT | name | フォーム入力値 | 必須 |
| INSERT | description | フォーム入力値 | 必須 |
| INSERT | is_disabled | !enabled（フォーム入力値の反転） | falseで有効 |

## メッセージ仕様

| メッセージ種別 | 表示条件 | メッセージ内容（i18nキー） |
|--------------|----------|------------------------|
| 成功 | 作成成功時 | salesChannels.toast.create |
| エラー | API呼び出し失敗時 | error.message |
| ラベル | 常時 | fields.name, fields.description, general.enabled |
| ヒント | 常時 | salesChannels.enabledHint |
| ボタン | 常時 | actions.cancel, actions.save |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| バリデーションエラー | Form.ErrorMessageコンポーネントでフィールドごとにエラー表示 |
| API呼び出しエラー | toast.error()でエラーメッセージを表示 |

## 備考

- zodResolverを使用したフォームバリデーション
- react-hook-formによるフォーム状態管理
- KeyboundFormコンポーネントによりキーボードショートカットが有効
- RouteFocusModalはフルスクリーンモーダル形式

---

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

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

### 推奨読解順序

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

まず、フォームのスキーマと送信データの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | create-sales-channel-form.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx` | CreateSalesChannelSchemaの定義（23-27行目） |

**読解のコツ**: zodスキーマでname、descriptionが必須（.min(1)）であることに注目してください。enabledはAPIではis_disabledに反転して送信されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sales-channel-create.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/sales-channel-create.tsx` | RouteFocusModalによるフルスクリーンモーダル構成 |

**主要処理フロー**:
1. **4-9行目**: RouteFocusModalでモーダルコンテナを構成
2. **7行目**: CreateSalesChannelFormコンポーネントを配置

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create-sales-channel-form.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx` | フォーム実装、バリデーション、API呼び出し |

**主要処理フロー**:
- **33-40行目**: useFormでフォーム状態を初期化（defaultValuesにデフォルト値を設定）
- **41行目**: useCreateSalesChannelフックでミューテーション関数を取得
- **43-58行目**: handleSubmit関数で作成処理を実行（enabledをis_disabledに変換）
- **60-154行目**: RouteFocusModal.Formでフォームをラップし、Input/Textarea/Switchコンポーネントを配置

#### Step 4: API呼び出しフックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sales-channels.tsx | `packages/admin/dashboard/src/hooks/api/sales-channels.tsx` | useCreateSalesChannelフックの実装（64-81行目） |

**主要処理フロー**:
- **72行目**: sdk.admin.salesChannel.create()を呼び出し
- **73-77行目**: 成功時にlistsクエリを無効化（キャッシュリフレッシュ）

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

```
SalesChannelCreate (sales-channel-create.tsx)
    │
    └─ RouteFocusModal
           └─ CreateSalesChannelForm (create-sales-channel-form.tsx)
                  │
                  ├─ useForm() → react-hook-form
                  │      └─ zodResolver(CreateSalesChannelSchema)
                  │
                  ├─ useCreateSalesChannel() → hooks/api/sales-channels.tsx
                  │
                  └─ handleSubmit()
                         └─ mutateAsync({ name, description, is_disabled })
                                └─ sdk.admin.salesChannel.create()
                                       │
                                       └─ onSuccess → handleSuccess(`../${sales_channel.id}`)
```

### データフロー図

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

フォーム入力 ──────────▶ useForm()
(name, description,       (バリデーション)
 enabled)                      │
                              ▼
                        handleSubmit()
                              │
                              ▼
                        値の変換
                        enabled → is_disabled
                              │
                              ▼
                        useCreateSalesChannel()
                              │
                              ▼
{ name, description,    sdk.admin.salesChannel.create() ───▶ sales_channel
  is_disabled }               │
                              ▼
                        toast.success()
                              │
                              ▼
                        handleSuccess(`../${id}`)
                              │
                              ▼
                        詳細画面へ遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sales-channel-create.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/sales-channel-create.tsx` | ソース | エントリーポイント |
| create-sales-channel-form.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx` | ソース | フォームコンポーネント |
| sales-channels.tsx | `packages/admin/dashboard/src/hooks/api/sales-channels.tsx` | ソース | APIフック（useCreateSalesChannel） |
| index.ts | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/index.ts` | ソース | バレルエクスポート |
| index.ts | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-create/components/create-sales-channel-form/index.ts` | ソース | フォームコンポーネントエクスポート |
