# 画面設計書 130-ロケーション一覧画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおけるロケーション（在庫保管場所）一覧画面の設計を記述したものです。システムに登録されている在庫ロケーションを一覧表示し、管理するための画面です。

### 本画面の処理概要

この画面では、システムに登録されている全ての在庫ロケーション（倉庫、店舗など）を一覧形式で表示し、各ロケーションの基本情報やフルフィルメント設定状況を確認できます。

**業務上の目的・背景**：ECサイト運営において、商品の在庫を保管する物理的な場所（倉庫、配送センター、店舗など）を管理することは、在庫管理と配送業務の基盤となります。ロケーションは、在庫レベルの追跡、配送オプションの設定、販売チャネルとの紐付けなど、フルフィルメント業務全体の起点となる重要なエンティティです。この画面は、登録されている全てのロケーションを俯瞰し、各ロケーションの詳細設定へナビゲートするためのハブとして機能します。

**画面へのアクセス方法**：設定メニューから「ロケーション」を選択してアクセスします。URLパスは `/settings/locations` です。TwoColumnPage形式（メインエリア＋サイドバー）で表示されます。

**主要な操作・処理内容**：
1. ロケーション一覧の表示（ページネーション、検索対応）
2. 各ロケーションの詳細画面へ遷移
3. 新しいロケーションの作成画面へ遷移
4. ロケーションの削除（確認ダイアログ付き）
5. サイドバーから配送プロファイル・配送オプションタイプ設定へナビゲート

**画面遷移**：
- 遷移元：設定メニュー
- 遷移先：ロケーション詳細画面（No.131）、ロケーション作成画面、配送プロファイル一覧、配送オプションタイプ一覧

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 73 | 在庫ロケーションCRUD | 主機能 | ロケーションの一覧表示・削除 |
| 76 | フルフィルメントセット管理 | 参照 | フルフィルメントセットの状態表示 |
| 70 | 販売チャネルCRUD | 参照 | 紐付けられた販売チャネルの表示 |

## 画面種別

一覧

## URL/ルーティング

`/settings/locations`

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| q | 入力（クエリパラメータ） | string | No | 検索キーワード |
| offset | 入力（クエリパラメータ） | number | No | ページネーションオフセット |
| order | 入力（クエリパラメータ） | string | No | ソート順 |
| stock_locations | 出力 | AdminStockLocation[] | - | ロケーション一覧 |
| count | 出力 | number | - | 総件数 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| ロケーション名 | string | ロケーションの名称 |
| 住所 | string | ロケーションの住所（フォーマット済み） |
| 配送フルフィルメント | StatusBadge | 配送フルフィルメントセットの有効/無効状態 |
| ピックアップフルフィルメント | StatusBadge | ピックアップフルフィルメントセットの有効/無効状態 |
| 販売チャネル | ListSummary | 紐付けられた販売チャネルの一覧（要約表示） |
| アクションメニュー | ActionMenu | 編集・削除アクション |

## イベント仕様

### 1-ロケーション行クリック

ロケーション行をクリックすると、該当ロケーションの詳細画面へ遷移します。

- 処理内容:
  - `/settings/locations/:id` へルーティング

### 2-作成ボタンクリック

テーブルヘッダーの「作成」ボタンをクリックすると、ロケーション作成画面へ遷移します。

- 処理内容:
  - `/settings/locations/create` へルーティング

### 3-編集アクションクリック

アクションメニューの「編集」をクリックすると、ロケーション編集画面へ遷移します。

- 処理内容:
  - `/settings/locations/:id/edit` へルーティング

### 4-削除アクションクリック

アクションメニューの「削除」をクリックすると、確認ダイアログを表示後、ロケーションを削除します。

- 処理内容:
  - usePromptで確認ダイアログを表示
  - 確認後、`DELETE /admin/stock-locations/:id` APIを呼び出し
  - 成功時: トースト通知を表示し、一覧を再取得
  - 失敗時: エラーメッセージをトースト通知で表示

### 5-配送プロファイルリンククリック

サイドバーの「配送プロファイル」リンクをクリックすると、配送プロファイル一覧画面へ遷移します。

- 処理内容:
  - `/settings/locations/shipping-profiles` へルーティング

### 6-配送オプションタイプリンククリック

サイドバーの「配送オプションタイプ」リンクをクリックすると、配送オプションタイプ一覧画面へ遷移します。

- 処理内容:
  - `/settings/locations/shipping-option-types` へルーティング

### 7-検索

検索フィールドに入力すると、ロケーション名で検索します。

- 処理内容:
  - クエリパラメータ `q` を更新
  - useStockLocationsフックが再実行されて検索結果を表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | stock_location | SELECT | ロケーション一覧の取得 |
| 削除アクション | stock_location | DELETE | ロケーションの削除 |

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

#### stock_location

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, address, fulfillment_sets, sales_channels | ページネーション条件、検索条件に基づく | LOCATION_LIST_FIELDSで指定 |
| DELETE | - | id = 削除対象ID | 論理削除 |

## メッセージ仕様

| メッセージ種別 | 表示条件 | メッセージ内容（i18nキー） |
|--------------|----------|------------------------|
| 見出し | 常時 | stockLocations.domain |
| 説明文 | 常時 | stockLocations.list.description |
| 空状態 | データなし | stockLocations.list.noRecordsMessage |
| 空状態説明（未フィルタ） | データなし | stockLocations.list.noRecordsMessageEmpty |
| 空状態説明（フィルタ済み） | 検索結果なし | stockLocations.list.noRecordsMessageFiltered |
| 削除確認タイトル | 削除時 | general.areYouSure |
| 削除確認説明 | 削除時 | stockLocations.delete.confirmation |
| 削除成功 | 削除成功時 | stockLocations.delete.successToast |
| 配送ステータス有効 | フルフィルメント有効 | statuses.enabled |
| 配送ステータス無効 | フルフィルメント無効 | statuses.disabled |
| サイドバーヘッダー | 常時 | stockLocations.sidebar.header |
| 配送プロファイルラベル | 常時 | stockLocations.sidebar.shippingProfiles.label |
| 配送プロファイル説明 | 常時 | stockLocations.sidebar.shippingProfiles.description |
| 配送オプションタイプラベル | 常時 | stockLocations.sidebar.shippingOptionTypes.label |
| 配送オプションタイプ説明 | 常時 | stockLocations.sidebar.shippingOptionTypes.description |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| API呼び出しエラー | エラーをスロー（isError状態）してエラーバウンダリでハンドリング |
| ローディング中 | DataTableにisLoading=trueを渡してローディング状態を表示 |
| 削除エラー | FetchErrorからメッセージを取得しトースト通知で表示 |

## 備考

- ページサイズは20件
- keepPreviousDataでページ遷移時のUXを向上
- LOCATION_LIST_FIELDSで取得フィールドを詳細に指定（address, sales_channels, fulfillment_sets等）
- 拡張ウィジェット用のスロットが4箇所用意されている（before, after, sideBefore, sideAfter）
- フルフィルメントセットの状態（Shipping/Pickup）をStatusBadgeで視覚的に表示
- 販売チャネルはListSummaryコンポーネントで要約表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.ts | `packages/admin/dashboard/src/routes/locations/location-list/constants.ts` | LOCATION_LIST_FIELDSの定義 |
| 1-2 | use-location-list-table-query.tsx | `packages/admin/dashboard/src/routes/locations/location-list/use-location-list-table-query.tsx` | AdminStockLocationListParams型のパラメータ構成 |

**読解のコツ**: LOCATION_LIST_FIELDSでは、*sales_channels, *address, *fulfillment_setsなど、関連エンティティをJOINして取得するフィールド指定が行われています。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | location-list.tsx | `packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx` | TwoColumnPageとDataTableの構成 |

**主要処理フロー**:
1. **16-17行目**: PAGE_SIZE=20, PREFIX="loc"の定数定義
2. **22-25行目**: useLocationListTableQueryでクエリパラメータを取得
3. **27-41行目**: useStockLocationsでロケーション一覧を取得
4. **43行目**: useLocationListTableColumnsでテーブルカラム定義を取得
5. **44行目**: useExtensionでウィジェットを取得
6. **50-98行目**: TwoColumnPage（メイン＋サイドバー）でレイアウト構成

#### Step 3: テーブルカラム定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | use-location-list-table-columns.tsx | `packages/admin/dashboard/src/routes/locations/location-list/use-location-list-table-columns.tsx` | カラム定義と削除処理 |

**主要処理フロー**:
- **29-61行目**: handleDelete関数（確認ダイアログ→API呼び出し→キャッシュ無効化→トースト）
- **65-78行目**: nameカラム定義
- **80-100行目**: addressカラム定義（getFormattedAddressでフォーマット）
- **101-138行目**: fulfillment_setsカラム（Shipping/Pickup別に2カラム）
- **139-158行目**: sales_channelsカラム（ListSummaryで要約表示）
- **159-181行目**: アクションカラム（編集・削除）

#### Step 4: API呼び出しフックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | stock-locations.tsx | `packages/admin/dashboard/src/hooks/api/stock-locations.tsx` | useStockLocations、useDeleteStockLocationフックの実装 |

**主要処理フロー**:
- **43-62行目**: useStockLocationsフックでリスト取得（sdk.admin.stockLocation.list）
- **133-155行目**: useDeleteStockLocationフックで削除（sdk.admin.stockLocation.delete）

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

```
LocationList (location-list.tsx)
    │
    ├─ useLocationListTableQuery() → use-location-list-table-query.tsx
    │      └─ useQueryParams(["order", "offset", "q"])
    │
    ├─ useStockLocations(query) → hooks/api/stock-locations.tsx
    │      └─ sdk.admin.stockLocation.list()
    │             └─ GET /admin/stock-locations
    │
    ├─ useLocationListTableColumns() → use-location-list-table-columns.tsx
    │      │
    │      ├─ handleDelete(location)
    │      │      ├─ prompt() → 確認ダイアログ
    │      │      ├─ sdk.admin.stockLocation.delete()
    │      │      │      └─ DELETE /admin/stock-locations/:id
    │      │      └─ queryClient.invalidateQueries()
    │      │
    │      └─ columnHelper.accessor() × 5カラム
    │             └─ columnHelper.action() → 編集・削除メニュー
    │
    ├─ useExtension()
    │      └─ getWidgets("location.list.*")
    │
    └─ TwoColumnPage
           │
           ├─ TwoColumnPage.Main
           │      └─ DataTable
           │             ├─ data: stockLocations
           │             ├─ columns: useLocationListTableColumns()
           │             ├─ rowHref: /settings/locations/:id
           │             ├─ actions: [{ to: "create" }]
           │             └─ emptyState: 空状態メッセージ
           │
           └─ TwoColumnPage.Sidebar
                  └─ LinksSection
                         ├─ SidebarLink → /settings/locations/shipping-profiles
                         └─ SidebarLink → /settings/locations/shipping-option-types
```

### データフロー図

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

URLクエリパラメータ ───▶ useLocationListTableQuery()
(q, offset, order)              │
                                ▼
                        useStockLocations({
                          fields: LOCATION_LIST_FIELDS,
                          ...searchParams
                        })                          ───▶ stock_locations[]
                                │                        count
                                ▼
                        useLocationListTableColumns()
                                │
                                ▼
                        DataTable表示
                        (name, address, fulfillment_sets,
                         sales_channels, actions)
                                │
                        ┌───────┴───────┐
                        │               │
行クリック ─────────▶ navigate()    アクション選択
                        │               │
                        ▼               ▼
                /settings/locations/:id  編集: navigate(/edit)
                (詳細画面)               削除: handleDelete()
                                              │
                                              ▼
                                        prompt() → 確認
                                              │
                                              ▼
                                        sdk.admin.stockLocation.delete()
                                              │
                                              ▼
                                        invalidateQueries()
                                              │
                                              ▼
                                        toast.success()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| location-list.tsx | `packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx` | ソース | エントリーポイント |
| use-location-list-table-columns.tsx | `packages/admin/dashboard/src/routes/locations/location-list/use-location-list-table-columns.tsx` | ソース | テーブルカラム定義・削除処理 |
| use-location-list-table-query.tsx | `packages/admin/dashboard/src/routes/locations/location-list/use-location-list-table-query.tsx` | ソース | クエリパラメータ処理 |
| constants.ts | `packages/admin/dashboard/src/routes/locations/location-list/constants.ts` | ソース | LOCATION_LIST_FIELDS定数 |
| stock-locations.tsx | `packages/admin/dashboard/src/hooks/api/stock-locations.tsx` | ソース | APIフック（useStockLocations, useDeleteStockLocation） |
| index.ts | `packages/admin/dashboard/src/routes/locations/location-list/index.ts` | ソース | バレルエクスポート |
