# 画面設計書 66-キャンペーン詳細画面

## 概要

本ドキュメントは、Medusa Admin Dashboard のキャンペーン詳細画面について、画面仕様・機能・データ処理を定義した画面設計書です。

### 本画面の処理概要

この画面では、キャンペーンの詳細情報を表示し、関連するプロモーション一覧の確認、キャンペーン情報の編集・削除、プロモーションの追加などのアクションを実行できます。

**業務上の目的・背景**：キャンペーンの全体像を把握し、関連プロモーションの管理を一元的に行うための画面です。キャンペーンのステータス（予定/有効/終了）、予算消化状況、期間設定などを確認し、必要に応じて設定を変更できます。また、キャンペーンに紐づくプロモーションの一覧を確認し、新たなプロモーションを追加したり、既存の紐付けを解除したりできます。

**画面へのアクセス方法**：キャンペーン一覧画面からキャンペーンをクリック、または直接URLでアクセスします。URL: `/campaigns/:id`

**主要な操作・処理内容**：
1. キャンペーンの基本情報（名前、識別子、説明、通貨）を確認
2. キャンペーンのステータス（scheduled/active/expired）を確認
3. キャンペーンの設定（開始日・終了日）を確認・編集
4. キャンペーンの予算（タイプ、上限、使用済み）を確認・編集
5. 関連プロモーション一覧を確認
6. プロモーションを追加
7. プロモーションとの紐付けを解除
8. キャンペーンを編集
9. キャンペーンを削除

**画面遷移**：
- 遷移元：キャンペーン一覧画面（`/campaigns`）
- 遷移先：キャンペーン編集画面、キャンペーン設定画面、予算編集画面、プロモーション追加画面、プロモーション詳細画面

**権限による表示制御**：認証済みの管理者ユーザーのみがアクセス可能です。キャンペーン管理権限を持つユーザーが操作できます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 38 | キャンペーン管理 | 主機能 | キャンペーン詳細の表示 |
| 36 | プロモーションCRUD | 補助機能 | 関連プロモーションの表示 |

## 画面種別

詳細

## URL/ルーティング

`/campaigns/:id`

## 入出力項目

なし（詳細表示画面のため）

## 表示項目

| 項目名 | 説明 |
|--------|------|
| キャンペーン名 | ヘッダーに表示 |
| ステータスバッジ | scheduled/active/expired |
| 識別子 | キャンペーン識別子 |
| 説明 | キャンペーンの説明 |
| 通貨 | 予算タイプがspendの場合のみ表示 |
| 設定セクション | 開始日・終了日 |
| 支出セクション | 使用済み予算 |
| 予算セクション | 予算タイプ、上限 |
| プロモーションセクション | 関連プロモーション一覧 |
| アクションメニュー | 編集・削除 |
| JSONビューア | キャンペーンのJSONデータ |
| メタデータ | キャンペーンのメタデータ |

## セクション構成

### メインエリア
- **基本情報セクション**: 名前、識別子、説明、通貨、ステータス
- **プロモーションセクション**: 関連プロモーション一覧（テーブル）

### サイドバー
- **設定セクション**: 開始日、終了日
- **支出セクション**: 使用済み予算
- **予算セクション**: 予算タイプ、上限

## イベント仕様

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

**処理フロー**：
1. `/campaigns/:id/edit` へ遷移
2. キャンペーン編集ドロワーを表示

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

**処理フロー**：
1. 確認ダイアログを表示
2. ユーザーがキャンセルした場合は処理終了
3. `useDeleteCampaign` フックを使用してAPIを呼び出し
4. 成功時：トースト通知を表示し、キャンペーン一覧画面へ遷移
5. 失敗時：エラーメッセージをトーストで表示

**API呼び出し**：
- エンドポイント: `DELETE /admin/campaigns/:id`

### 3-設定編集ボタン押下

**処理フロー**：
1. `/campaigns/:id/configuration` へ遷移
2. キャンペーン設定編集ドロワーを表示

### 4-予算編集ボタン押下

**処理フロー**：
1. `/campaigns/:id/edit-budget` へ遷移
2. 予算編集ドロワーを表示

### 5-プロモーション追加ボタン押下

**処理フロー**：
1. `/campaigns/:id/add-promotions` へ遷移
2. プロモーション追加モーダルを表示

### 6-プロモーション紐付け解除

**処理フロー**：
1. 確認ダイアログを表示
2. `useAddOrRemoveCampaignPromotions` フックを使用してAPIを呼び出し（remove操作）
3. 成功時：トースト通知を表示し、一覧を更新
4. 失敗時：エラーメッセージをトーストで表示

**API呼び出し**：
- エンドポイント: `POST /admin/campaigns/:id/promotions`
- リクエストボディ: `{ "remove": [promotion_id] }`

### 7-プロモーション行クリック

**処理フロー**：
1. `/promotions/:id` へ遷移
2. プロモーション詳細画面を表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 削除アクション選択 | campaign | DELETE | キャンペーンの削除 |
| プロモーション紐付け解除 | promotion | UPDATE | campaign_idをnullに更新 |

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

#### campaign

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | キャンペーンID | 削除 |

#### promotion

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | campaign_id | null | 紐付け解除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | 確認 | キャンペーン「{name}」を削除しますか？ | 削除アクション選択時 |
| MSG-002 | 成功 | キャンペーン「{name}」を削除しました | 削除成功時 |
| MSG-003 | 成功 | プロモーションの紐付けを解除しました | 紐付け解除成功時 |
| MSG-004 | エラー | {エラーメッセージ} | API通信エラー時 |

## 例外処理

| 例外 | 処理内容 |
|------|---------|
| キャンペーンが見つからない | エラーをスローしてエラー画面を表示 |
| API通信エラー | エラーメッセージをtoastで表示 |

## 備考

- ステータスはキャンペーンの開始日・終了日から動的に計算される
  - scheduled: 開始日が未来
  - active: 開始日が過去で終了日が未来または未設定
  - expired: 終了日が過去
- 通貨は予算タイプがspendの場合のみ表示される
- 画面はTwoColumnPageレイアウトを使用（メイン + サイドバー）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.ts | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/constants.ts` | CAMPAIGN_DETAIL_FIELDSでデータ取得フィールドを確認 |
| 1-2 | campaign-status.ts | `packages/admin/dashboard/src/routes/campaigns/common/utils/campaign-status.ts` | ステータス計算ロジック |

**読解のコツ**: キャンペーンのステータスはstarts_atとends_atから動的に計算されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | campaign-detail.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx` | TwoColumnPageレイアウトと各セクションの配置 |

**主要処理フロー**:
1. **17-19行目**: useLoaderDataでプリロードデータを取得
2. **21-26行目**: useCampaignでキャンペーン詳細を取得
3. **45-67行目**: TwoColumnPageでメインとサイドバーをレンダリング

#### Step 3: 各セクションコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | campaign-general-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-general-section/campaign-general-section.tsx` | 基本情報表示と編集・削除アクション |
| 3-2 | campaign-promotion-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-promotion-section/campaign-promotion-section.tsx` | プロモーション一覧と追加・解除アクション |
| 3-3 | campaign-configuration-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-configuration-section/campaign-configuration-section.tsx` | 設定セクション |
| 3-4 | campaign-spend.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-spend/campaign-spend.tsx` | 支出セクション |
| 3-5 | campaign-budget.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-budget/campaign-budget.tsx` | 予算セクション |

**主要処理フロー（campaign-general-section.tsx）**:
- **32行目**: useDeleteCampaignで削除ミューテーション準備
- **34-61行目**: handleDeleteで削除処理
- **64行目**: campaignStatus()でステータス計算

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

```
CampaignDetail (campaign-detail.tsx)
    │
    ├─ useLoaderData() - プリロードデータ取得
    │
    ├─ useCampaign() - キャンペーン詳細取得
    │      └─ sdk.admin.campaign.retrieve()
    │             └─ GET /admin/campaigns/:id
    │
    ├─ TwoColumnPage.Main
    │      │
    │      ├─ CampaignGeneralSection
    │      │      │
    │      │      ├─ campaignStatus() - ステータス計算
    │      │      │
    │      │      └─ useDeleteCampaign() - 削除処理
    │      │             └─ DELETE /admin/campaigns/:id
    │      │
    │      └─ CampaignPromotionSection
    │             │
    │             └─ useAddOrRemoveCampaignPromotions() - 紐付け解除
    │                    └─ POST /admin/campaigns/:id/promotions
    │
    └─ TwoColumnPage.Sidebar
           │
           ├─ CampaignConfigurationSection
           │
           ├─ CampaignSpend
           │
           └─ CampaignBudget
```

### データフロー図

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

URLパラメータ ────▶ useLoaderData ───▶ プリロードデータ
     (id)                                      ↓
                    useCampaign() ────▶ キャンペーン詳細
                                              ↓
                  campaignStatus() ───▶ ステータス計算
                                              ↓
                                        TwoColumnPage表示
                                              ↓
削除アクション ───▶ usePrompt() ────▶ 確認ダイアログ
                          ↓
                  useDeleteCampaign() ▶ API削除
                          ↓
                  navigate("/campaigns") ▶ 一覧画面遷移

紐付け解除 ───────▶ usePrompt() ────▶ 確認ダイアログ
                          ↓
                  useAddOrRemoveCampaignPromotions() ▶ API更新
                          ↓
                  invalidateQueries() ▶ データ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| campaign-detail.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx` | ソース | エントリーポイント |
| campaign-general-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-general-section/campaign-general-section.tsx` | ソース | 基本情報セクション |
| campaign-promotion-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-promotion-section/campaign-promotion-section.tsx` | ソース | プロモーションセクション |
| campaign-configuration-section.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-configuration-section/campaign-configuration-section.tsx` | ソース | 設定セクション |
| campaign-spend.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-spend/campaign-spend.tsx` | ソース | 支出セクション |
| campaign-budget.tsx | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/components/campaign-budget/campaign-budget.tsx` | ソース | 予算セクション |
| constants.ts | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/constants.ts` | ソース | 定数定義 |
| loader.ts | `packages/admin/dashboard/src/routes/campaigns/campaign-detail/loader.ts` | ソース | プリローダー |
| campaigns.tsx | `packages/admin/dashboard/src/hooks/api/campaigns.tsx` | ソース | APIフック |
