# 画面設計書 159-タイプメタデータ編集画面

## 概要

本ドキュメントは、Medusa Admin Dashboard における商品タイプのメタデータ編集画面の設計仕様を定義するものである。

### 本画面の処理概要

タイプメタデータ編集画面は、特定の商品タイプに関連付けられたメタデータ（カスタムキー・バリューペア）を管理するための画面である。サイドドロワー形式で表示され、メタデータの追加、編集、削除が可能。

**業務上の目的・背景**：商品タイプに対してカスタム情報を付与する必要がある場合、メタデータを使用する。例えば、タイプ固有の属性（表示優先度、カスタムフラグなど）を柔軟に設定できる。これにより、標準項目では対応できないビジネス要件に対応可能。

**画面へのアクセス方法**：
1. 商品タイプ詳細画面で「メタデータ」セクションの編集ボタンをクリック
2. 直接URL `/settings/product-types/{id}/metadata` にアクセス

**主要な操作・処理内容**：
1. 現在のメタデータがキー・バリューペアのリストとして表示される
2. 「追加」ボタンで新しいメタデータ行を追加する
3. キー・バリューを入力または編集する
4. 各行の削除ボタンで不要なメタデータを削除する
5. 「保存」ボタンをクリックしてすべての変更を保存

**画面遷移**：
- 遷移元：商品タイプ詳細画面（No.157）
- 遷移先：保存成功時は遷移元に戻る（モーダルクローズ）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | 商品タイプ管理 | 主機能 | 商品タイプのメタデータ編集 |

## 画面種別

編集（サイドドロワー形式）

## URL/ルーティング

- パス: `/settings/product-types/:id/metadata`
- コンポーネント: `ProductTypeMetadata`
- ドロワータイプ: `RouteDrawer`（MetadataForm内部で使用）

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 最小長 | 最大長 | 備考 |
|--------|--------|-----|------|--------|--------|------|
| メタデータ配列 | metadata | array | No | - | - | キー・バリューペアの配列 |
| キー | metadata[n].key | string | Yes | 1 | - | 各メタデータのキー |
| 値 | metadata[n].value | string | Yes | 1 | - | 各メタデータの値 |

## 表示項目

| 項目名 | 説明 | 表示位置 |
|--------|------|----------|
| ヘッダータイトル | 「メタデータ」 | ドロワーヘッダー |
| ヒント | メタデータに関する説明テキスト | ヘッダー下 |
| メタデータリスト | キー・バリューペアのリスト | ボディ |
| 追加ボタン | 新しい行を追加 | リスト下 |
| キャンセルボタン | 「キャンセル」 | フッター左 |
| 保存ボタン | 「保存」 | フッター右 |

## イベント仕様

### 1-行追加（追加ボタン押下）

1. 新しい空のキー・バリューペア行をフォームに追加
2. useFieldArray の `append` メソッドを使用

### 2-行削除（削除ボタン押下）

1. 対象の行をフォームから削除
2. useFieldArray の `remove` メソッドを使用

### 3-フォーム送信（保存ボタン押下）

1. フォームバリデーションを実行（Zodスキーマによる検証）
2. メタデータ配列をオブジェクト形式に変換
3. `useUpdateProductType` フックを通じて API 呼び出し
4. 成功時:
   - トースト通知「メタデータが更新されました」を表示
   - `handleSuccess()` でドロワーを閉じる
5. 失敗時:
   - エラーメッセージをトースト通知で表示

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

1. ドロワーを閉じる
2. 前の画面（商品タイプ詳細画面）に戻る

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | product_type | SELECT | タイプ詳細情報の取得（メタデータ含む） |
| 保存ボタン押下 | product_type | UPDATE | メタデータの更新 |

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

#### product_type（参照）

| 操作 | 項目（カラム名） | 取得条件 | 備考 |
|-----|-----------------|---------|------|
| SELECT | id, metadata | WHERE id = :id | 現在のメタデータ取得 |

#### product_type（更新）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | metadata | フォームで入力されたキー・バリューオブジェクト | JSON形式 |
| UPDATE | updated_at | システム日時 | 更新日時 |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 | 表示条件 |
|------|---------------|---------------|----------|
| 成功 | metadata.edit.successToast | メタデータが更新されました | 更新成功時 |
| エラー | （APIエラーメッセージ） | APIからのエラーメッセージを表示 | 更新失敗時 |
| バリデーション | （Zodエラー） | キーまたは値が必須です | 空の場合 |

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| タイプが存在しない | エラーをスロー（エラー境界でキャッチ） |
| ネットワークエラー | エラーメッセージをトースト通知で表示 |
| サーバーエラー | APIからのエラーメッセージをトースト通知で表示 |
| データ読み込み中 | スケルトンローダーを表示 |

## 備考

- 共通の MetadataForm コンポーネントを使用
- フォーム状態管理には react-hook-form の useFieldArray を使用
- バリデーションには Zod スキーマを使用
- キャッシュ無効化: 更新成功時に `productTypesQueryKeys.detail(id)` と `productTypesQueryKeys.lists()` のキャッシュを無効化
- メタデータはキー・バリュー配列 → オブジェクト形式に変換して API に送信

---

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

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

### 推奨読解順序

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

処理の起点となるコンポーネントを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ProductTypeMetadata | `packages/admin/dashboard/src/routes/product-types/product-type-metadata/product-type-metadata.tsx` | MetadataForm を使用するシンプルなラッパー |

**主要処理フロー**:
1. **行6**: useParams でURLから id を取得
2. **行8**: useProductType でタイプデータを取得
3. **行10-12**: useUpdateProductType フックを取得
4. **行14-16**: エラー時はエラーをスロー
5. **行18-25**: MetadataForm に必要なpropsを渡してレンダリング

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

メタデータ編集の共通ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MetadataForm | `packages/admin/dashboard/src/components/forms/metadata-form/metadata-form.tsx` | キー・バリューペアを動的に編集するフォーム |

**主要処理フロー**:
- useFieldArray でメタデータ配列を動的に管理
- append で行追加、remove で行削除
- handleSubmit でオブジェクト形式に変換してAPI呼び出し

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

バックエンドとの通信を担うフックの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | useProductType | `packages/admin/dashboard/src/hooks/api/product-types.tsx:17-36` | タイプ詳細取得 |
| 3-2 | useUpdateProductType | `packages/admin/dashboard/src/hooks/api/product-types.tsx:109-126` | メタデータを含む更新 |

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

```
ProductTypeMetadata（エントリーポイント）
    │
    ├─ useParams() → id 取得
    │
    ├─ useProductType(id)
    │      └─ sdk.admin.productType.retrieve()
    │
    ├─ useUpdateProductType(id)
    │      └─ useMutation
    │
    └─ MetadataForm
           │
           ├─ useForm (react-hook-form)
           │      └─ useFieldArray → metadata 配列管理
           │
           ├─ RouteDrawer
           │      ├─ Header: 「メタデータ」
           │      ├─ Body: キー・バリューフィールドリスト
           │      └─ Footer: キャンセル / 保存
           │
           └─ handleSubmit
                  │
                  ├─ 配列 → オブジェクト変換
                  │
                  ├─ hook(mutateAsync)
                  │      └─ sdk.admin.productType.update({ metadata })
                  │
                  ├─ onSuccess → toast.success() + handleSuccess()
                  └─ onError → toast.error()
```

### データフロー図

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

URL params (id) ───▶ ProductTypeMetadata ───▶ 遷移元画面に戻る
                          │
                          ├─ useProductType
                          │      │
                          │      └─ GET /admin/product-types/{id}
                          │              │
                          │              └─ product_type.metadata（現在値）
                          │
                          └─ MetadataForm
                                 │
                                 ├─ 入力: metadata[] (キー・バリュー配列)
                                 │
                                 ├─ 変換: 配列 → オブジェクト
                                 │
                                 └─ POST /admin/product-types/{id}
                                        │
                                        └─ { metadata: { key: value, ... } }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| product-type-metadata.tsx | `packages/admin/dashboard/src/routes/product-types/product-type-metadata/product-type-metadata.tsx` | ソース | エントリーポイント |
| metadata-form.tsx | `packages/admin/dashboard/src/components/forms/metadata-form/metadata-form.tsx` | ソース | 共通メタデータフォーム |
| product-types.tsx | `packages/admin/dashboard/src/hooks/api/product-types.tsx` | ソース | 商品タイプ関連APIフック |
| index.ts | `packages/admin/dashboard/src/routes/product-types/product-type-metadata/index.ts` | ソース | モジュールエクスポート |
