# 画面設計書 30-カテゴリ詳細画面

## 概要

本ドキュメントは、Medusa Admin Dashboard における「カテゴリ詳細画面」の設計仕様を定義するものである。

### 本画面の処理概要

カテゴリ詳細画面は、商品カテゴリの詳細情報を表示し、カテゴリの編集・削除およびカテゴリに属する商品の管理を行うための画面である。

**業務上の目的・背景**：カテゴリの詳細情報（名称、説明、ハンドル、ステータス、可視性）を確認し、必要に応じて編集や削除を行う。また、カテゴリに属する商品の一覧を確認し、商品の追加・削除が可能。さらに、カテゴリの階層構造（親カテゴリへのパス、子カテゴリ一覧）を視覚的に把握できる。

**画面へのアクセス方法**：カテゴリ一覧画面でカテゴリ行をクリック、またはカテゴリ作成後の自動遷移でアクセス可能。URLは `/categories/:id` の形式となる。

**主要な操作・処理内容**：
1. カテゴリ基本情報の表示（名称、説明、ハンドル、ステータス、可視性）
2. カテゴリの編集画面への遷移
3. カテゴリの削除
4. 階層構造の表示（パス、子カテゴリ）
5. 所属商品の一覧表示、追加、削除
6. メタデータの表示・編集
7. JSONデータの表示

**画面遷移**：カテゴリ編集画面、カテゴリ整理画面、商品追加画面、子カテゴリ詳細画面への遷移が可能。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | 商品カテゴリ管理 | 主機能 | カテゴリの詳細表示・編集・削除 |

## 画面種別

詳細

## URL/ルーティング

`/categories/:id`

## 入出力項目

| 項目名 | 項目ID | データ型 | 必須 | 入力/出力 | 説明 |
|--------|--------|----------|------|-----------|------|
| カテゴリID | id | string | 必須 | 入力（URLパラメータ） | 表示対象のカテゴリID |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| カテゴリ名 | Heading | カテゴリの名称 |
| ステータスバッジ | StatusBadge | アクティブ/非アクティブの状態 |
| 可視性バッジ | StatusBadge | 公開/内部の可視性設定 |
| 説明 | Text | カテゴリの説明文（未設定時は「-」） |
| ハンドル | Text | URLスラッグ（先頭に/付与） |
| 階層パス | PathDisplay | 親カテゴリへのパス（展開可能） |
| 子カテゴリ | ChildrenDisplay | 子カテゴリのバッジリスト（クリックで遷移） |
| 商品一覧テーブル | DataTable | カテゴリに属する商品の一覧 |
| メタデータセクション | JsonViewSection | メタデータの表示・編集 |
| JSONセクション | JsonViewSection | 生データのJSON表示 |

## イベント仕様

### 1-編集アクション選択

アクションメニューから「編集」を選択すると、カテゴリ編集画面（/categories/:id/edit）に遷移する。

### 2-翻訳管理アクション選択

翻訳機能が有効な場合、アクションメニューから「翻訳を管理」を選択すると、翻訳編集画面に遷移する。

### 3-削除アクション選択

アクションメニューから「削除」を選択すると、確認ダイアログを表示後、カテゴリを削除する。成功時はカテゴリ一覧画面に遷移する。

### 4-整理アクション選択

階層セクションのアクションメニューから「整理」を選択すると、カテゴリ整理画面（/categories/:id/organize）に遷移する。

### 5-パス展開/折りたたみ

階層パスが複数ある場合、「...」をクリックしてパス全体を展開/折りたたみする。

### 6-子カテゴリクリック

子カテゴリのバッジをクリックすると、その子カテゴリの詳細画面に遷移する。

### 7-商品追加

商品セクションのアクションメニューから「追加」を選択すると、商品追加画面（/categories/:id/products）に遷移する。

### 8-商品選択・削除

商品一覧で商品をチェックボックスで選択し、コマンドバーの「削除」を選択またはショートカットキー「r」を押下すると、確認ダイアログ後にカテゴリから商品を削除する。

### 9-商品行クリック

商品一覧の行をクリックすると、その商品の詳細画面に遷移する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 削除アクション選択 | product_category | DELETE | カテゴリを削除 |
| 商品選択・削除 | product_category_product（中間テーブル） | DELETE | カテゴリと商品の紐付けを削除 |

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

#### product_category

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | id = URLパラメータのカテゴリID | 子カテゴリがある場合は削除不可 |

#### product_category_product

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | product_id, category_id | 選択された商品IDとカテゴリID | removeパラメータで指定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| categories.organize.header | ヘッダー | 階層 | 階層セクションヘッダー |
| categories.fields.path.label | ラベル | パス | パスフィールドラベル |
| categories.fields.path.tooltip | ツールチップ | パスを展開 | パス省略時のツールチップ |
| categories.fields.children.label | ラベル | 子カテゴリ | 子カテゴリフィールドラベル |
| products.domain | ヘッダー | 商品 | 商品セクションヘッダー |
| categories.products.list.noRecordsMessage | 説明 | このカテゴリには商品がありません | 商品がない場合の表示 |
| categories.products.remove.confirmation | 確認 | {count}件の商品をカテゴリから削除しますか？ | 商品削除確認 |
| categories.products.remove.successToast | 成功 | {count}件の商品が削除されました | 商品削除成功時 |
| categories.delete.confirmation | 確認 | {name}を削除してもよろしいですか？ | カテゴリ削除確認 |
| categories.delete.successToast | 成功 | {name}が削除されました | カテゴリ削除成功時 |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| カテゴリが見つからない | エラーをthrowし、エラーバウンダリで処理 |
| 親カテゴリ取得失敗 | エラーをthrowし、エラーバウンダリで処理 |
| 子カテゴリ取得失敗 | エラーをthrowし、エラーバウンダリで処理 |
| 商品削除失敗 | トースト通知でエラーメッセージを表示 |
| カテゴリ削除失敗 | トースト通知でエラーメッセージを表示 |

## 備考

- TwoColumnPageレイアウトを使用（メイン2セクション、サイドバー1セクション）
- useProductCategoryフックでカテゴリデータを取得
- categoryLoaderでSSR/初期データ取得
- useLoaderDataで初期データを取得しuseProductCategoryのinitialDataに渡す
- showJSON/showMetadataでJSONセクション・メタデータセクションを表示
- 拡張ポイント：product_category.details.before/after、product_category.details.side.before/afterでウィジェット追加可能
- PathDisplayコンポーネントで親カテゴリの階層パスを表示（展開/折りたたみ可能）
- ChildrenDisplayコンポーネントで子カテゴリをバッジ表示
- CategoryProductSectionで商品一覧をCommandBar付きで表示
- useUpdateProductCategoryProductsで商品の追加・削除
- 翻訳機能フラグ（translation）で翻訳管理アクションの表示を制御

---

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

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

### 推奨読解順序

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

カテゴリのデータ構造と関連するAPIレスポンスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | useProductCategoryでカテゴリデータ取得（21-27行目） |
| 1-2 | category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | useLoaderDataで初期データ取得（15-17行目） |

**読解のコツ**: initialDataを使用することでSSRと連携し、初期表示を高速化している。

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

ルートコンポーネントの処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | useParamsでカテゴリID取得（13行目） |
| 2-2 | category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | TwoColumnPageでレイアウト構成（44-63行目） |
| 2-3 | category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | 3つのセクションコンポーネント（57-61行目） |

**主要処理フロー**:
1. **13行目**: useParamsでURLパラメータからカテゴリIDを取得
2. **15-17行目**: useLoaderDataで初期データを取得
3. **19行目**: useExtensionでカスタムウィジェットを取得
4. **21-27行目**: useProductCategoryでカテゴリデータを取得
5. **44-63行目**: TwoColumnPageでレイアウトを構成し、各セクションを描画

#### Step 3: 基本情報セクションを理解する

カテゴリの基本情報表示を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | category-general-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-general-section/category-general-section.tsx` | getIsActiveProps/getIsInternalPropsでステータス表示（20-21行目） |
| 3-2 | category-general-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-general-section/category-general-section.tsx` | useDeleteProductCategoryActionで削除（23行目） |
| 3-3 | category-general-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-general-section/category-general-section.tsx` | ActionMenuでアクション定義（38-72行目） |

#### Step 4: 階層セクションを理解する

親カテゴリパスと子カテゴリの表示を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | category-organize-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-organize-section/category-organize-section.tsx` | PathDisplayで親カテゴリパス表示（60-170行目） |
| 4-2 | category-organize-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-organize-section/category-organize-section.tsx` | ChildrenDisplayで子カテゴリ表示（172-216行目） |
| 4-3 | category-organize-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-organize-section/category-organize-section.tsx` | include_ancestors_tree/include_descendants_treeで階層取得（74-77, 182-185行目） |

**主要処理フロー**:
- **PathDisplay**: useProductCategoryでinclude_ancestors_tree=trueを指定し、親カテゴリの階層を取得
- **ChildrenDisplay**: useProductCategoryでinclude_descendants_tree=trueを指定し、子カテゴリを取得
- **getCategoryPath/getCategoryChildren**: ユーティリティ関数で階層データを整形

#### Step 5: 商品セクションを理解する

カテゴリに属する商品の一覧と操作を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | category-product-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-product-section/category-product-section.tsx` | useProductsでカテゴリの商品取得（40-48行目） |
| 5-2 | category-product-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-product-section/category-product-section.tsx` | useUpdateProductCategoryProductsで商品削除（67行目） |
| 5-3 | category-product-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-product-section/category-product-section.tsx` | CommandBarで選択時アクション（146-160行目） |

**主要処理フロー**:
- **37行目**: useStateで選択状態管理
- **40-48行目**: useProductsでcategory_idフィルター付きで商品取得
- **67行目**: useUpdateProductCategoryProductsで商品の追加・削除
- **69-104行目**: handleRemoveで商品削除処理
- **146-160行目**: CommandBarで「削除」アクション（ショートカット「r」）

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

```
CategoryDetail (category-detail.tsx:12-65)
    │
    ├─ useParams() → カテゴリID取得
    │
    ├─ useLoaderData() → 初期データ取得
    │      └─ categoryLoader()
    │
    ├─ useExtension() → ウィジェット取得
    │
    ├─ useProductCategory(id) → カテゴリデータ取得
    │      └─ sdk.admin.productCategory.retrieve()
    │
    └─ TwoColumnPage
           │
           ├─ TwoColumnPage.Main
           │      │
           │      ├─ CategoryGeneralSection
           │      │      │
           │      │      ├─ getIsActiveProps() → ステータス表示
           │      │      ├─ getIsInternalProps() → 可視性表示
           │      │      ├─ useDeleteProductCategoryAction()
           │      │      │      └─ useDeleteProductCategory()
           │      │      │             └─ sdk.admin.productCategory.delete()
           │      │      │
           │      │      └─ ActionMenu → 編集・翻訳・削除
           │      │
           │      └─ CategoryProductSection
           │             │
           │             ├─ useProducts(category_id) → 商品取得
           │             │
           │             ├─ useUpdateProductCategoryProducts()
           │             │      └─ sdk.admin.productCategory.updateProducts()
           │             │
           │             ├─ useDataTable() → テーブル状態管理
           │             │
           │             └─ CommandBar → 商品削除
           │
           └─ TwoColumnPage.Sidebar
                  │
                  └─ CategoryOrganizeSection
                         │
                         ├─ PathDisplay
                         │      └─ useProductCategory(include_ancestors_tree)
                         │             └─ getCategoryPath()
                         │
                         └─ ChildrenDisplay
                                └─ useProductCategory(include_descendants_tree)
                                       └─ getCategoryChildren()
```

### データフロー図

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

URLパラメータ(id) ─────────────▶ useParams ───▶ カテゴリID
                                          │
                                          ▼
                              ┌─────────────────────┐
                              │ useProductCategory   │
                              │ (initialData付き)    │
                              └─────────────────────┘
                                          │
                                          ▼
                              ┌─────────────────────┐
                              │ product_category    │
                              │ データ取得完了       │
                              └─────────────────────┘
                                          │
                  ┌───────────────────────┼───────────────────────┐
                  ▼                       ▼                       ▼
          CategoryGeneralSection  CategoryProductSection  CategoryOrganizeSection
                  │                       │                       │
                  │                       │               ┌───────┴───────┐
                  │                       │               ▼               ▼
                  │                       │         PathDisplay    ChildrenDisplay
                  │                       │               │               │
                  │                       │               ▼               ▼
                  │                       │      useProductCategory useProductCategory
                  │                       │      (ancestors_tree)  (descendants_tree)
                  │                       │               │               │
                  │                       │               ▼               ▼
                  │                       │        getCategoryPath getCategoryChildren
                  │                       │               │               │
                  ▼                       ▼               ▼               ▼
            ステータス表示         商品一覧テーブル     パス表示      子カテゴリ表示
                  │                       │
                  │               ┌───────┴───────┐
                  │               ▼               ▼
                  │          選択状態管理    CommandBar
                  │               │               │
                  │               └───────┬───────┘
                  │                       ▼
                  │              handleRemove ───▶ 商品削除
                  │
編集選択 ─────────▶ /categories/:id/edit
削除選択 ─────────▶ handleDelete ───▶ カテゴリ削除
                                          │
                                          ▼
                                  /categoriesに遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| category-detail.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/category-detail.tsx` | ソース | 画面のエントリーポイント |
| loader.ts | `packages/admin/dashboard/src/routes/categories/category-detail/loader.ts` | ソース | SSR用データローダー |
| category-general-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-general-section/category-general-section.tsx` | ソース | 基本情報セクション |
| category-organize-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-organize-section/category-organize-section.tsx` | ソース | 階層構造セクション |
| category-product-section.tsx | `packages/admin/dashboard/src/routes/categories/category-detail/components/category-product-section/category-product-section.tsx` | ソース | 商品一覧セクション |
| use-delete-product-category-action.tsx | `packages/admin/dashboard/src/routes/categories/common/hooks/use-delete-product-category-action.tsx` | ソース | カテゴリ削除アクションフック |
| useProductCategory | `packages/admin/dashboard/src/hooks/api/categories.ts` | ソース | カテゴリ取得フック |
| useUpdateProductCategoryProducts | `packages/admin/dashboard/src/hooks/api/categories.ts` | ソース | カテゴリ商品更新フック |
| useDeleteProductCategory | `packages/admin/dashboard/src/hooks/api/categories.ts` | ソース | カテゴリ削除フック |
| useProducts | `packages/admin/dashboard/src/hooks/api/products.ts` | ソース | 商品一覧取得フック |
| TwoColumnPage | `packages/admin/dashboard/src/components/layout/pages/` | ソース | 2カラムページレイアウト |
| CommandBar | `@medusajs/ui` | 外部 | コンテキストアクションバー |
