# 画面設計書 112-ストアメタデータ編集画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおけるストアのメタデータ編集画面に関する設計書です。この画面により、ストアに紐づくカスタムメタデータをキー・バリュー形式で管理することができます。

### 本画面の処理概要

**業務上の目的・背景**：Eコマースシステムでは、標準のデータモデルでは対応できない独自の情報を保持する必要があることがあります。メタデータ機能により、開発者やシステム管理者がストアに対してカスタム属性を柔軟に追加・編集できます。これは外部システムとの連携や、カスタマイズされたビジネスロジックの実装に不可欠な機能です。

**画面へのアクセス方法**：ストア詳細画面（/settings/store）からメタデータセクションの「編集」ボタンをクリック、またはJSON表示エリアの編集アクションからアクセスできます。URL直接アクセスも可能（/settings/store/metadata）。

**主要な操作・処理内容**：
1. 既存のメタデータをキー・バリュー形式のグリッドで表示
2. 新規メタデータ行の追加（上または下に挿入）
3. 既存メタデータの編集（キーと値の変更）
4. メタデータ行の削除
5. 複雑な値（オブジェクト・配列）は読み取り専用で表示
6. 変更内容の保存

**画面遷移**：
- 遷移元：ストア詳細画面（/settings/store）
- 遷移先：保存成功時・キャンセル時ともにストア詳細画面に戻る

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 68 | ストアCRUD | 主機能 | ストアメタデータの編集 |

## 画面種別

ドロワー形式（RouteDrawer）の編集画面

## URL/ルーティング

`/settings/store/metadata`

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| メタデータ配列 | metadata | MetadataField[] | - | キー・値・disabled状態の配列 |
| メタデータキー | metadata[].key | string | - | メタデータのキー名 |
| メタデータ値 | metadata[].value | any | - | メタデータの値 |
| 編集不可フラグ | metadata[].disabled | boolean | - | 複雑な値の場合true |

## 表示項目

### メタデータグリッド

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|------|------|
| キー | key | string | メタデータのキー |
| 値 | value | string/any | メタデータの値（複雑な値は{ ... }や[ ... ]で表示） |
| 行アクションメニュー | actions | - | 上に挿入/下に挿入/削除 |

## イベント仕様

### 1-行の追加（上に挿入）

**トリガー**：行のアクションメニューから「上に行を挿入」を選択

**処理内容**：
1. useFieldArrayのinsertを使用
2. 指定インデックスの位置に空の行を挿入
3. 新しい行はkey: "", value: "", disabled: falseで初期化

### 2-行の追加（下に挿入）

**トリガー**：行のアクションメニューから「下に行を挿入」を選択

**処理内容**：
1. useFieldArrayのinsertを使用
2. 指定インデックス+1の位置に空の行を挿入

### 3-行の削除

**トリガー**：行のアクションメニューから「行を削除」を選択

**処理内容**：
1. useFieldArrayのremoveを使用
2. 指定インデックスの行を削除
3. 最後の1行を削除した場合は、自動的に空の行を追加

### 4-保存

**トリガー**：「保存」ボタンをクリック

**処理内容**：
1. フォーム値をパース（parseValues関数）
   - 空のキーはスキップ
   - "true"/"false"文字列はブール値に変換
   - 数値文字列は数値型に変換
   - 削除されたキーは空文字列で上書き（削除マーカー）
2. useUpdateStoreフックでストア更新APIを呼び出し
3. 成功時：トースト通知を表示し、ドロワーを閉じる
4. 失敗時：エラートースト通知を表示

### 5-キャンセル

**トリガー**：「キャンセル」ボタンをクリック

**処理内容**：
1. ドロワーを閉じてストア詳細画面に戻る

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | store | UPDATE | ストアのmetadataフィールドを更新 |

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

#### store

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | metadata | パースされたメタデータオブジェクト | 削除キーは空文字列 |
| UPDATE | updated_at | 現在日時 | 自動更新 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| metadata.edit.successToast | 成功 | メタデータが更新されました | 保存成功時 |
| - | エラー | {エラーメッセージ} | API呼び出し失敗時 |
| metadata.edit.complexRow.tooltip | 情報 | この行は編集できません | 複雑な値の行にホバー時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ストア情報取得エラー | エラーをスローしてエラーバウンダリで処理 |
| 更新API失敗 | エラートーストを表示、フォームは維持 |
| 複雑な値（オブジェクト/配列） | 編集不可として表示、削除も不可 |

## 備考

- オブジェクトや配列などの複雑な値は編集不可（読み取り専用）
- 複雑な値がある場合は警告メッセージ（InlineTip）を表示
- 値の型は自動判定される（true/false->boolean、数値文字列->number）
- 全ての行を削除するとnullがAPIに送信される

---

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

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

### 推奨読解順序

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

メタデータのデータ構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | metadata-form.tsx | `packages/admin/dashboard/src/components/forms/metadata-form/metadata-form.tsx` | MetadataFieldSchemaの定義（42-46行目） |

**読解のコツ**: メタデータはkey, value, disabledの3フィールドを持つオブジェクトの配列として管理されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | store-metadata.tsx | `packages/admin/dashboard/src/routes/store/store-metadata/store-metadata.tsx` | コンポーネントのエントリーポイント |

**主要処理フロー**:
1. **6行目**: useStoreでストア情報を取得
2. **8行目**: useUpdateStoreでストア更新フックを取得
3. **14-23行目**: RouteDrawerでMetadataFormをラップ

#### Step 3: フォームロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | metadata-form.tsx | `packages/admin/dashboard/src/components/forms/metadata-form/metadata-form.tsx` | 汎用メタデータフォームコンポーネント |

**主要処理フロー**:
- **42-50行目**: Zodスキーマ定義
- **84-89行目**: useFormでフォーム初期化、getDefaultValuesで初期値設定
- **91-108行目**: handleSubmit - parseValuesでデータ変換後API呼び出し
- **110-113行目**: useFieldArrayで配列フィールド管理
- **115-126行目**: deleteRow - 最後の行削除時は空行を自動追加
- **128-134行目**: insertRow - 上または下に新規行を挿入
- **333-367行目**: getDefaultValues - 既存メタデータの初期化
- **369-428行目**: parseValues - フォーム値のパース（型変換、削除マーカー設定）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | store.tsx | `packages/admin/dashboard/src/hooks/api/store.tsx` | ストアAPIフック |

**主要処理フロー**:
- **36-58行目**: useStore - ストア情報取得
- **60-83行目**: useUpdateStore - metadataを含むストア更新

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

```
StoreMetadata (store-metadata.tsx)
    │
    ├─ useStore()
    │      └─ sdk.admin.store.list()
    │
    ├─ useUpdateStore()
    │      └─ sdk.admin.store.update()
    │
    └─ MetadataForm
           │
           ├─ useForm() + useFieldArray()
           │      └─ フォーム状態管理
           │
           ├─ getDefaultValues()
           │      └─ 既存メタデータの変換
           │
           └─ parseValues()
                  └─ 保存用データ変換
```

### データフロー図

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

既存metadata ─────▶ getDefaultValues() ─────▶ フォーム初期値
                           │
                           ▼
キー/値の編集 ────▶ フォーム状態管理 ────────▶ fields配列
                           │
                           ▼
保存ボタン押下 ──▶ parseValues() ───────────▶ 更新用metadata
                           │                    (型変換済み)
                           ▼
                 useUpdateStore API呼び出し
                           │
                           ▼
                  [Store APIサーバー]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| store-metadata.tsx | `packages/admin/dashboard/src/routes/store/store-metadata/store-metadata.tsx` | ソース | エントリーポイント |
| metadata-form.tsx | `packages/admin/dashboard/src/components/forms/metadata-form/metadata-form.tsx` | ソース | 汎用メタデータフォーム |
| store.tsx | `packages/admin/dashboard/src/hooks/api/store.tsx` | ソース | ストアAPIフック |
| route-drawer.tsx | `packages/admin/dashboard/src/components/modals/route-drawer/` | ソース | ドロワーコンポーネント |
