# 画面設計書 5-商品一覧画面

## 概要

本ドキュメントは、Medusa Admin Dashboard の商品一覧画面の設計仕様を定義するものです。登録されている商品を一覧表示し、検索・フィルタ・ソート機能を提供する商品管理の中心的な画面です。

### 本画面の処理概要

本画面は、ECサイトに登録された商品の一覧を表示し、効率的な商品管理を支援する画面です。ページネーション、検索、多彩なフィルタ機能を備え、大量の商品を効率的に管理できます。また、商品のインポート・エクスポート、新規作成への導線も提供します。

**業務上の目的・背景**：ECサイトでは数百〜数万点の商品を管理することがあり、それらを効率的に閲覧・検索・管理する機能が不可欠です。本画面は、商品管理者が目的の商品を素早く見つけ、各種操作（編集・削除・詳細確認）へアクセスするためのハブとして機能します。また、商品データの一括インポート・エクスポート機能により、外部システムとの連携や一括更新作業を効率化します。

**画面へのアクセス方法**：
- サイドナビゲーションの「商品」メニューから
- ダッシュボードから直接 `/products` へアクセス
- 他の商品関連画面からの戻り遷移

**主要な操作・処理内容**：
1. 商品一覧の表示 - ページネーション付きで商品を一覧表示
2. 検索 - 商品名やその他の属性で検索
3. フィルタ - タイプ、タグ、販売チャネル、ステータス、日付で絞り込み
4. ソート - タイトル、作成日、更新日で並び替え
5. 商品の選択と詳細画面への遷移
6. インポート/エクスポート画面への遷移
7. 新規商品作成画面への遷移
8. 商品の編集・削除アクション

**画面遷移**：
- 遷移元：サイドナビゲーション、ダッシュボード
- 遷移先：商品詳細画面、商品作成画面、商品編集画面、商品インポート画面、商品エクスポート画面、翻訳管理画面

**権限による表示制御**：本画面は認証済みユーザーのみアクセス可能です。翻訳管理機能はフィーチャーフラグ（translation）により制御されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 商品CRUD | 主機能 | 商品の一覧取得・検索・フィルタ処理 |
| 88 | インデックス検索 | 補助機能 | 商品の高速検索 |

## 画面種別

一覧画面

## URL/ルーティング

`/products`

## 入出力項目

### 検索・フィルタパラメータ

| 項目名 | 項目ID | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| 検索クエリ | q | string | 任意 | フリーテキスト検索 |
| タイプ | type_id | string[] | 任意 | 商品タイプでフィルタ |
| タグ | tag_id | string[] | 任意 | 商品タグでフィルタ |
| 販売チャネル | sales_channel_id | string[] | 任意 | 販売チャネルでフィルタ |
| ステータス | status | string[] | 任意 | 商品ステータスでフィルタ |
| 作成日 | created_at | DateFilter | 任意 | 作成日でフィルタ |
| 更新日 | updated_at | DateFilter | 任意 | 更新日でフィルタ |
| ページ | offset | number | 任意 | ページネーションオフセット |
| 件数 | limit | number | 任意 | 1ページあたりの表示件数（デフォルト: 20） |
| 並び順 | order | string | 任意 | ソート条件（title, created_at, updated_at） |

## 表示項目

### テーブルヘッダー

| 項目名 | 表示位置 | データソース | 説明 |
|--------|----------|--------------|------|
| タイトル | ヘッダー左 | i18n (products.domain) | 「商品」タイトル |
| エクスポートボタン | ヘッダー右 | i18n (actions.export) | エクスポート画面へのリンク |
| インポートボタン | ヘッダー右 | i18n (actions.import) | インポート画面へのリンク |
| 作成ボタン | ヘッダー右 | i18n (actions.create) | 商品作成画面へのリンク |

### テーブル列

| 項目名 | カラムID | データソース | 説明 |
|--------|----------|--------------|------|
| サムネイル | thumbnail | product.thumbnail | 商品のサムネイル画像 |
| タイトル | title | product.title | 商品名 |
| コレクション | collection | product.collection.title | 所属コレクション |
| 販売チャネル | sales_channels | product.sales_channels | 販売チャネル数 |
| 在庫数量 | inventory | 集計値 | バリアント在庫の合計 |
| ステータス | status | product.status | 商品ステータス（draft/published/proposed/rejected） |
| アクション | actions | - | 編集・翻訳・削除メニュー |

### フィルタ

| 項目名 | データソース | 説明 |
|--------|--------------|------|
| タイプフィルタ | useProductTypes | 商品タイプによる絞り込み |
| タグフィルタ | useProductTags | 商品タグによる絞り込み |
| 販売チャネルフィルタ | useSalesChannels | 販売チャネルによる絞り込み |
| ステータスフィルタ | 静的 | draft/proposed/published/rejected |
| 日付フィルタ | useDataTableDateFilters | 作成日・更新日による絞り込み |

## イベント仕様

### 1-テーブル行クリック

**トリガー**: テーブル行のクリック

**処理フロー**:
1. クリックされた行の商品IDを取得
2. `navigateTo={(row) => ${row.original.id}}` により商品詳細画面へ遷移

**遷移先**: 商品詳細画面（/products/{productId}）

### 2-作成ボタン押下

**トリガー**: 「作成」ボタンのクリック

**処理フロー**:
1. React Router の Link コンポーネントによるページ遷移

**遷移先**: 商品作成画面（/products/create）

### 3-エクスポートボタン押下

**トリガー**: 「エクスポート」ボタンのクリック

**処理フロー**:
1. 現在のフィルタ条件（location.search）を維持したまま遷移

**遷移先**: 商品エクスポート画面（/products/export + 現在のクエリパラメータ）

### 4-インポートボタン押下

**トリガー**: 「インポート」ボタンのクリック

**処理フロー**:
1. 現在のフィルタ条件（location.search）を維持したまま遷移

**遷移先**: 商品インポート画面（/products/import + 現在のクエリパラメータ）

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

**トリガー**: アクションメニューの「編集」選択

**処理フロー**:
1. 対象商品のIDを取得
2. 編集画面へ遷移

**遷移先**: 商品編集画面（/products/{productId}/edit）

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

**トリガー**: アクションメニューの「翻訳を管理」選択（translationフィーチャーフラグ有効時のみ）

**処理フロー**:
1. 対象商品のIDを取得
2. 翻訳編集画面へ遷移

**遷移先**: 翻訳編集画面（/settings/translations/edit?reference=product&reference_id={productId}）

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

**トリガー**: アクションメニューの「削除」選択

**処理フロー**:
1. 確認プロンプトを表示
2. ユーザーが確認した場合、`useDeleteProduct` フックで削除APIを呼び出し
3. 成功時: トースト通知で成功メッセージを表示
4. 失敗時: トースト通知でエラーメッセージを表示

### 8-検索入力

**トリガー**: 検索フィールドへの入力

**処理フロー**:
1. 入力値をクエリパラメータに反映
2. `useProductTableQuery` フックが自動的にAPI呼び出し
3. 結果を再表示

### 9-フィルタ選択

**トリガー**: フィルタ条件の選択/変更

**処理フロー**:
1. フィルタ条件をクエリパラメータに反映
2. `useProductTableQuery` フックが自動的にAPI呼び出し
3. 結果を再表示

### 10-ソート変更

**トリガー**: ソート列の選択

**処理フロー**:
1. 選択可能なソートキー: title, created_at, updated_at
2. クエリパラメータにソート条件を反映
3. `useProductTableQuery` フックが自動的にAPI呼び出し
4. 結果を再ソートして表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | product | SELECT | 商品一覧の取得 |
| 検索/フィルタ | product | SELECT | 条件に一致する商品の取得 |
| 削除 | product | DELETE (soft) | 商品の論理削除 |

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

#### product

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | フィルタ条件に基づく | 一覧取得時 |
| SELECT | * | is_giftcard = false | ギフトカードを除外 |
| DELETE | deleted_at | 現在日時 | 論理削除時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| products.toasts.delete.success.header | 成功 | 商品を削除しました | 削除成功時 |
| products.toasts.delete.success.description | 成功 | {title}を削除しました | 削除成功時 |
| products.toasts.delete.error.header | エラー | 削除に失敗しました | 削除失敗時 |
| products.deleteWarning | 確認 | {title}を削除しますか？ | 削除確認プロンプト |
| products.list.noRecordsMessage | 情報 | 商品が見つかりません | 検索結果が0件の場合 |

## 例外処理

| 例外条件 | 処理内容 | ユーザーへの表示 |
|---------|---------|-----------------|
| API取得エラー | エラーをスロー | エラー境界でキャッチして表示 |
| 削除API失敗 | トーストでエラー表示 | エラーメッセージをトーストで表示 |
| 検索結果なし | 空状態メッセージ表示 | 「商品が見つかりません」メッセージ |

## 備考

- 本画面は認証済みユーザーのみアクセス可能なプロテクト画面です
- ページサイズは20件固定です
- ギフトカード（is_giftcard = true）は商品一覧から除外されます
- フィーチャーフラグ「view_configurations」が有効な場合、ConfigurableProductListTableコンポーネントが使用されます
- フィーチャーフラグ「translation」が有効な場合、翻訳管理アクションが表示されます
- 拡張機能により、画面の前後にカスタムウィジェットを追加可能です（product.list.before / product.list.after）

---

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

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

### 推奨読解順序

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

まず、商品データの型定義を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types | `@medusajs/types` | HttpTypes.AdminProduct 型定義 |

**読解のコツ**: `HttpTypes.AdminProduct` はMedusaの型定義パッケージで定義されています。

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

ProductListコンポーネントから処理の流れを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | product-list.tsx | `packages/admin/dashboard/src/routes/products/product-list/product-list.tsx` | メインコンポーネント |
| 2-2 | index.ts | `packages/admin/dashboard/src/routes/products/product-list/index.ts` | エクスポート定義 |

**主要処理フロー**:
1. **6行目**: useExtensionでウィジェット取得
2. **8-16行目**: SingleColumnPageレイアウトでProductListTableを表示

#### Step 3: テーブルコンポーネントを理解する

ProductListTableコンポーネントの詳細を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | product-list-table.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/product-list-table.tsx` | テーブル実装 |

**主要処理フロー**:
1. **26-106行目**: ProductListTableコンポーネント
2. **29-30行目**: フィーチャーフラグによるテーブル切り替え
3. **40-50行目**: useProductsフックでデータ取得
4. **52-62行目**: フィルタとカラム定義の取得
5. **68-106行目**: DataTableコンポーネントでテーブル描画

#### Step 4: フィルタ機能を理解する

フィルタフックの実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | use-product-table-filters.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/use-product-table-filters.tsx` | フィルタ定義 |

**主要処理フロー**:
- **19-32行目**: 商品タイプ、タグ、販売チャネルの取得
- **37-99行目**: フィルタ定義（タイプ、タグ、販売チャネル、ステータス）

#### Step 5: アクションメニューを理解する

商品アクションコンポーネントを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | product-list-table.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/product-list-table.tsx` | 109-182行目: ProductActionsコンポーネント |

**主要処理フロー**:
- **111-112行目**: usePromptとuseDeleteProductフックの取得
- **115-143行目**: handleDelete関数（確認→削除→通知）
- **145-181行目**: ActionMenuコンポーネント（編集、翻訳、削除）

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

```
ProductList (product-list.tsx)
    │
    └─ ProductListTable (product-list-table.tsx)
           │
           ├─ useProductTableQuery (hooks/table/query)
           │      └─ URL パラメータからクエリ生成
           │
           ├─ useProducts (hooks/api/products.tsx)
           │      └─ sdk.admin.product.list
           │           └─ Backend Products API
           │
           ├─ useProductTableFilters (use-product-table-filters.tsx)
           │      ├─ useProductTypes
           │      ├─ useProductTags
           │      └─ useSalesChannels
           │
           ├─ useProductTableColumns (hooks/table/columns)
           │
           ├─ useDataTable
           │
           └─ ProductActions
                  ├─ useDeleteProduct
                  └─ usePrompt
```

### データフロー図

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

検索クエリ ───┐
              │
フィルタ ────┼──▶ useProductTableQuery ───▶ URLパラメータ
              │            │
ソート ──────┘            ▼
                    useProducts
                         │
                         ▼
                  sdk.admin.product.list
                         │
                         ▼
              HttpTypes.AdminProduct[]
                         │
                         ▼
                  useDataTable ───▶ table 状態
                         │
                         ▼
                   _DataTable ───▶ テーブルUI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| product-list.tsx | `packages/admin/dashboard/src/routes/products/product-list/product-list.tsx` | ソース | 商品一覧画面のメインコンポーネント |
| product-list-table.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/product-list-table.tsx` | ソース | 商品テーブルコンポーネント |
| use-product-table-filters.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/use-product-table-filters.tsx` | ソース | フィルタ定義フック |
| configurable-product-list-table.tsx | `packages/admin/dashboard/src/routes/products/product-list/components/product-list-table/configurable-product-list-table.tsx` | ソース | 設定可能テーブル（フィーチャーフラグ時） |
| loader.ts | `packages/admin/dashboard/src/routes/products/product-list/loader.ts` | ソース | ローダー関数 |
| index.ts | `packages/admin/dashboard/src/routes/products/product-list/index.ts` | ソース | エクスポート定義 |
| products.tsx | `packages/admin/dashboard/src/hooks/api/products.tsx` | ソース | 商品APIフック |
| use-product-table-columns.tsx | `packages/admin/dashboard/src/hooks/table/columns/use-product-table-columns.tsx` | ソース | テーブル列定義 |
| use-product-table-query.tsx | `packages/admin/dashboard/src/hooks/table/query/use-product-table-query.tsx` | ソース | クエリパラメータ管理 |
