# 画面設計書 127-販売チャネル編集画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおける販売チャネル編集画面の設計を記述したものです。販売チャネルの基本情報を編集するためのモーダル形式のドロワー画面です。

### 本画面の処理概要

この画面では、既存の販売チャネルの名前、説明、有効/無効状態を編集できます。

**業務上の目的・背景**：ECサイト運営において、販売チャネルの情報は時間とともに変更が必要になることがあります。チャネル名の変更、説明の更新、一時的なチャネルの無効化などの操作が、日常的な運用業務として発生します。この画面は、そうした変更を簡単かつ安全に行うためのインターフェースを提供します。

**画面へのアクセス方法**：販売チャネル詳細画面（No.126）または一覧画面（No.124）のアクションメニューから「編集」を選択してアクセスします。URLパスは `/settings/sales-channels/:id/edit` です。RouteDrawer形式（サイドパネル）で表示されます。

**主要な操作・処理内容**：
1. 販売チャネル名の編集（必須）
2. 説明の編集（任意）
3. 有効/無効状態の切り替え
4. 保存ボタンクリックで更新
5. キャンセルボタンクリックでドロワーを閉じる

**画面遷移**：
- 遷移元：販売チャネル詳細画面（No.126）、販売チャネル一覧画面（No.124）
- 遷移先：保存完了後、遷移元画面へ戻る

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 70 | 販売チャネルCRUD | 主機能 | 販売チャネル情報の編集 |

## 画面種別

編集（モーダル形式）

## URL/ルーティング

`/settings/sales-channels/:id/edit`

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| id | 入力（URLパラメータ） | string | Yes | 販売チャネルID |
| name | 入力（フォーム） | string | Yes | 販売チャネル名（1文字以上） |
| description | 入力（フォーム） | string | No | 説明（任意） |
| is_active | 入力（フォーム） | boolean | Yes | 有効/無効状態 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| ヘッダータイトル | string | 「販売チャネルを編集」（i18n: salesChannels.editSalesChannel） |
| 名前入力フィールド | Input | name入力欄 |
| 説明入力フィールド | Textarea | description入力欄（任意） |
| 有効スイッチ | Switch | is_active切り替え |
| ヒントテキスト | string | 有効化の説明（i18n: salesChannels.enabledHint） |

## イベント仕様

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

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

- バリデーション:
  - name: 必須、1文字以上の文字列
  - description: オプショナル
  - is_active: boolean（is_disabledに変換して送信）
- 処理内容:
  - `POST /admin/sales-channels/:id` APIを呼び出し（useUpdateSalesChannelフック）
  - リクエストボディ: `{ name, description, is_disabled: !is_active }`
  - 成功時: トースト通知を表示し、ドロワーを閉じる
  - 失敗時: エラーメッセージをトースト通知で表示

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

キャンセルボタンをクリックすると、変更を保存せずにドロワーを閉じます。

### 3-フォーム入力

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

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | sales_channel | SELECT | 販売チャネル情報の取得 |
| 保存ボタン押下 | sales_channel | UPDATE | 販売チャネル情報の更新 |

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

#### sales_channel

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, description, is_disabled | id = URLパラメータのid | フォーム初期値設定用 |
| UPDATE | name | フォーム入力値 | 必須 |
| UPDATE | description | フォーム入力値 | nullの場合はundefined |
| UPDATE | is_disabled | !is_active（フォーム入力値の反転） | trueで無効 |

## メッセージ仕様

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

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 販売チャネルが見つからない | エラーをスロー（isError状態）してエラーバウンダリでハンドリング |
| ローディング中 | EditSalesChannelFormを表示しない（条件付きレンダリング） |
| バリデーションエラー | Form.ErrorMessageコンポーネントでフィールドごとにエラー表示 |

## 備考

- zodResolverを使用したフォームバリデーション
- react-hook-formによるフォーム状態管理
- KeyboundFormコンポーネントによりキーボードショートカットが有効
- descriptionフィールドにはoptionalラベルが表示される

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: zodスキーマでnameが必須、descriptionがオプショナルであることに注目してください。is_activeはAPIではis_disabledに反転して送信されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sales-channel-edit.tsx | `packages/admin/dashboard/src/routes/sales-channels/sales-channel-edit/sales-channel-edit.tsx` | RouteDrawerによるドロワー構成、useSalesChannelでのデータ取得 |

**主要処理フロー**:
1. **10行目**: useParamsでURLからIDを取得
2. **13-18行目**: useSalesChannelでデータ取得
3. **24-35行目**: RouteDrawerでドロワー構成、EditSalesChannelFormを配置

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

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

**主要処理フロー**:
- **29-36行目**: useFormでフォーム状態を初期化（is_disabledを反転してis_activeに変換）
- **38行目**: useUpdateSalesChannelフックでミューテーション関数を取得
- **40-57行目**: handleSubmit関数で更新処理（is_activeをis_disabledに再変換）
- **59-136行目**: RouteDrawer.Formでフォームをラップし、Input/Textarea/Switchコンポーネントを配置

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

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

**主要処理フロー**:
- **91行目**: sdk.admin.salesChannel.update()を呼び出し
- **92-99行目**: 成功時にlistsとdetailクエリを無効化

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

```
SalesChannelEdit (sales-channel-edit.tsx)
    │
    ├─ useParams() → id取得
    │
    ├─ useSalesChannel(id)
    │      └─ sdk.admin.salesChannel.retrieve()
    │
    └─ RouteDrawer
           └─ EditSalesChannelForm (edit-sales-channel-form.tsx)
                  │
                  ├─ useForm() → react-hook-form
                  │      └─ zodResolver(EditSalesChannelSchema)
                  │
                  ├─ useUpdateSalesChannel(id)
                  │
                  └─ handleSubmit()
                         └─ mutateAsync({ name, description, is_disabled })
                                └─ sdk.admin.salesChannel.update()
```

### データフロー図

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

URLパラメータ(:id) ───▶ useParams()              ───▶ id
                              │
                              ▼
                        useSalesChannel(id)      ───▶ sales_channel
                              │
                              ▼
sales_channel.name     useForm()
sales_channel.description  (defaultValues設定)
!sales_channel.is_disabled → is_active
                              │
                              ▼
フォーム入力 ──────────▶ handleSubmit()
(name, description,           │
 is_active)                   ▼
                        値の変換
                        is_active → is_disabled
                              │
                              ▼
{ name, description,    useUpdateSalesChannel()
  is_disabled }               │
                              ▼
                        sdk.admin.salesChannel.update() ───▶ sales_channel
                              │
                              ▼
                        toast.success()
                              │
                              ▼
                        handleSuccess() → ドロワー閉じる
```

### 関連ファイル一覧

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