# 画面設計書 153-商品タグ編集画面

## 概要

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

### 本画面の処理概要

商品タグ編集画面は、既存の商品タグの名前（value）を更新するためのモーダル形式の画面である。管理者は商品タグ詳細画面のアクションメニューから本画面を開き、タグ名を変更して保存することができる。

**業務上の目的・背景**：商品タグは商品の分類やマーケティング施策において使用されるが、業務の変化や命名規則の統一などにより、既存のタグ名を変更する必要が生じることがある。この画面を通じて、既存タグの名称を容易に更新でき、システム全体の一貫性を維持することができる。

**画面へのアクセス方法**：
1. 商品タグ詳細画面のアクションメニューから「編集」を選択
2. 商品タグ一覧画面の各行のアクションメニューから「編集」を選択
3. 直接URL `/settings/product-tags/{id}/edit` にアクセス

**主要な操作・処理内容**：
1. 既存のタグ名が入力フィールドに表示される
2. タグ名を編集する
3. 「保存」ボタンをクリックして変更を保存する
4. 「キャンセル」ボタンで編集をキャンセルしてドロワーを閉じる

**画面遷移**：
- 遷移元：商品タグ詳細画面（No.152）、商品タグ一覧画面（No.150）
- 遷移先：編集完了後は遷移元に戻る（ドロワーを閉じる）

**権限による表示制御**：認証済みの管理ユーザーのみがアクセス可能。特定のロールによる制限は現時点では実装されていない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | 商品タグ管理 | 主機能 | 商品タグ情報の編集 |

## 画面種別

編集（モーダル/ドロワー形式）

## URL/ルーティング

- パス: `/settings/product-tags/:id/edit`
- コンポーネント: `ProductTagEdit`
- モーダルタイプ: `RouteDrawer`

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 最小長 | 最大長 | 備考 |
|--------|--------|-----|------|--------|--------|------|
| タグ名 | value | string | Yes | 1 | - | 既存のタグ名が初期値として設定される |

## 表示項目

| 項目名 | 説明 | 表示位置 |
|--------|------|----------|
| ヘッダータイトル | 「商品タグを編集」 | ドロワーヘッダー |
| サブタイトル | 編集に関する説明文 | ヘッダー下（sr-only） |
| タグ名ラベル | 「値」 | 入力フィールド上 |
| キャンセルボタン | 「キャンセル」 | フッター左 |
| 保存ボタン | 「保存」 | フッター右 |

## イベント仕様

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

1. フォームバリデーションを実行（Zodスキーマによる検証）
2. バリデーション成功時、`useUpdateProductTag` フックを通じて API 呼び出し
3. API呼び出し: `sdk.admin.productTag.update(id, data)`
4. 成功時:
   - トースト通知「タグ "{value}" が更新されました」を表示
   - ドロワーを閉じ、前の画面に戻る
5. 失敗時:
   - エラーメッセージをトースト通知で表示

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

1. ドロワーを閉じる
2. 前の画面（商品タグ詳細画面または一覧画面）に戻る

### 3-キーボードショートカット

- `KeyboundForm` コンポーネントにより、Enter キーでフォーム送信が可能

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | product_tag | SELECT | 既存タグ情報の取得 |
| 保存ボタン押下 | product_tag | UPDATE | タグ名の更新 |

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

#### product_tag

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, value | WHERE id = :id | 編集対象タグの取得 |
| UPDATE | value | 入力された新しい値 | タグ名 |
| UPDATE | updated_at | システム日時 | 更新日時 |

## メッセージ仕様

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

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| タグが存在しない | エラーをスロー（エラー境界でキャッチ） |
| ネットワークエラー | エラーメッセージをトースト通知で表示、フォームは保持 |
| サーバーエラー | APIからのエラーメッセージをトースト通知で表示 |
| 重複エラー | APIからのエラーメッセージをトースト通知で表示 |

## 備考

- ドロワーは `RouteDrawer` コンポーネントを使用しており、画面右側からスライドインする形式
- フォーム状態管理には react-hook-form を使用
- バリデーションには Zod スキーマを使用
- キャッシュ無効化: 更新成功時に `productTagsQueryKeys.lists()` と `productTagsQueryKeys.detail(id)` のキャッシュを無効化
- データ読み込み中は ProductTagEditForm コンポーネントは表示されない（ready フラグで制御）

---

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

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

### 推奨読解順序

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

まず、商品タグのデータ構造と更新用の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | HttpTypes | `@medusajs/types` | `AdminUpdateProductTag`, `AdminProductTag` の型定義 |
| 1-2 | ProductTagEditSchema | `product-tag-edit-form.tsx:17-19` | Zodによるバリデーションスキーマの定義 |

**読解のコツ**: スキーマは作成画面と同じ `z.object({ value: z.string().min(1) })` だが、defaultValues に既存のタグ名を設定している点が異なる。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ProductTagEdit | `packages/admin/dashboard/src/routes/product-tags/product-tag-edit/product-tag-edit.tsx` | RouteDrawer でラップされたエントリーポイント |

**主要処理フロー**:
1. **行9**: useParams で id を取得
2. **行12**: useProductTag でタグデータを取得
3. **行14**: ready フラグでローディング状態を管理
4. **行20-31**: RouteDrawer 内にヘッダーとフォームを配置

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ProductTagEditForm | `packages/admin/dashboard/src/routes/product-tags/product-tag-edit/components/product-tag-edit-form/product-tag-edit-form.tsx` | 編集フォームのロジックとUI |

**主要処理フロー**:
1. **行21-30**: useForm による初期化、defaultValues に既存のタグ名を設定
2. **行32**: useUpdateProductTag フックの呼び出し（id を引数に渡す）
3. **行34-48**: handleSubmit 関数でフォーム送信処理
4. **行50-87**: JSX レンダリング

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | useUpdateProductTag | `packages/admin/dashboard/src/hooks/api/tags.tsx:113-136` | useMutation による更新API呼び出し |

**主要処理フロー**:
- **行123**: `sdk.admin.productTag.update(id, data, query)` による API 呼び出し
- **行124-130**: 成功時にリストと詳細のキャッシュを無効化

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

```
ProductTagEdit（エントリーポイント）
    │
    ├─ useParams（id 取得）
    │
    ├─ useProductTag（既存データ取得）
    │      └─ sdk.admin.productTag.retrieve()
    │
    └─ RouteDrawer
           │
           ├─ RouteDrawer.Header（タイトル）
           │
           └─ ProductTagEditForm（ready 時のみ表示）
                  │
                  ├─ useForm (react-hook-form)
                  │      ├─ defaultValues: { value: productTag.value }
                  │      └─ zodResolver (Zod バリデーション)
                  │
                  ├─ useUpdateProductTag
                  │      └─ useMutation
                  │             └─ sdk.admin.productTag.update()
                  │
                  └─ handleSubmit
                         ├─ onSuccess → toast.success() + handleSuccess()
                         └─ onError → toast.error()
```

### データフロー図

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

URL params (id) ───▶ ProductTagEdit ───▶ ドロワーを閉じる
                          │
                          ├─ useProductTag (既存データ取得)
                          │      │
                          │      └─ GET /admin/product-tags/{id}
                          │              │
                          │              └─ product_tag データ
                          │
value (string) ───▶ ProductTagEditForm
                          │
                          ├─ Zod バリデーション
                          │
                          ├─ useUpdateProductTag
                          │      │
                          │      └─ PUT /admin/product-tags/{id}
                          │              │
                          │              └─ 更新された product_tag
                          │
                          └─ handleSuccess()
                                 │
                                 └─ ドロワーを閉じる
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| product-tag-edit.tsx | `packages/admin/dashboard/src/routes/product-tags/product-tag-edit/product-tag-edit.tsx` | ソース | エントリーポイントコンポーネント |
| product-tag-edit-form.tsx | `packages/admin/dashboard/src/routes/product-tags/product-tag-edit/components/product-tag-edit-form/product-tag-edit-form.tsx` | ソース | 編集フォームコンポーネント |
| tags.tsx | `packages/admin/dashboard/src/hooks/api/tags.tsx` | ソース | 商品タグ関連APIフック |
| index.ts | `packages/admin/dashboard/src/routes/product-tags/product-tag-edit/index.ts` | ソース | モジュールエクスポート |
