# 画面設計書 44-ランディングページ

## 概要

本ドキュメントは、Shopware 6 Administration（管理画面）における「ランディングページ」画面の設計書です。この画面はマーケティング目的のランディングページを作成・管理するための機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：ECサイトにおいてランディングページは、キャンペーン、プロモーション、特集ページなどマーケティング施策を実施する上で重要な役割を果たします。カテゴリ構造に縛られない独立したページを作成し、専用のURLでアクセス可能にすることで、柔軟なコンテンツ展開が可能になります。本画面はランディングページの作成、編集、管理を行う機能を提供しますが、実際のUI実装はカテゴリ管理画面（sw-category-detail）と共通化されています。

**画面へのアクセス方法**：管理画面にログイン後、左側メニューの「カタログ」→「カテゴリ」からアクセスし、ランディングページタブを選択するか、検索機能からランディングページを検索してアクセスします。URLパスは `/admin#/sw/landing/page/index` となりますが、実際には `sw.category.detail.base` へリダイレクトされます。

**主要な操作・処理内容**：
1. ランディングページ一覧の表示 - カテゴリツリーと同様の階層構造で表示
2. ランディングページの作成 - 新規ランディングページの作成
3. ランディングページの編集 - 名前、URL、CMSレイアウト、SEO設定などの編集
4. ランディングページの削除 - 不要なランディングページの削除
5. CMSレイアウトの割当 - ショッピングエクスペリエンスの選択と適用
6. SEO設定 - メタタイトル、メタディスクリプション、SEO URLの設定
7. アクティブ/非アクティブ切替 - 公開状態の制御

**画面遷移**：
- 遷移元: カテゴリ管理画面、検索結果
- 遷移先: CMS詳細画面（レイアウト編集時）

**権限による表示制御**：
ランディングページはカテゴリモジュールの権限を使用します：
- `category.viewer`: 閲覧権限 - ランディングページの表示が可能
- `category.creator`: 作成権限 - 新規作成が可能
- `category.editor`: 編集権限 - 編集が可能
- `category.deleter`: 削除権限 - 削除が可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 63 | ランディングページ表示 | 主機能 | ランディングページの作成・管理 |

## 画面種別

詳細/編集（カテゴリ管理画面と共通UI）

## URL/ルーティング

- **パス**: `/admin#/sw/landing/page/index`
- **コンポーネント**: `sw-category-detail`（リダイレクト先）
- **ルート名**: `sw.landing.page.index`
- **リダイレクト先**: `sw.category.detail.base`
- **必要権限**: `category.viewer`

## 入出力項目

| 項目名 | 種別 | 型 | 必須 | 説明 |
|--------|------|-----|------|------|
| name | 入力 | string | 必須 | ランディングページ名 |
| active | 入力 | boolean | - | 有効/無効フラグ |
| url | 入力 | string | 必須 | SEO URL |
| metaTitle | 入力 | string | - | SEOメタタイトル |
| metaDescription | 入力 | string | - | SEOメタディスクリプション |
| keywords | 入力 | string | - | SEOキーワード |
| cmsPageId | 入力 | string | - | 割り当てるCMSページのID |
| salesChannels | 入力 | array | 必須 | 公開する販売チャネル |
| customFields | 入力 | object | - | カスタムフィールド |

## 表示項目

| 項目名 | カラム名 | 説明 | 編集可否 |
|--------|----------|------|----------|
| ページ名 | name | ランディングページの名称 | string |
| アクティブ | active | 公開状態 | boolean |
| URL | url | SEO URL | string |
| 販売チャネル | salesChannels | 公開先チャネル | array |
| CMSレイアウト | cmsPage | 適用されているレイアウト | select |
| 作成日時 | createdAt | 作成日時 | - |
| 更新日時 | updatedAt | 最終更新日時 | - |

## イベント仕様

### 1-ランディングページ作成

新規作成ボタンをクリックしてランディングページを作成。

**処理フロー**:
1. 新規ランディングページエンティティを作成
2. 必須項目（名前、URL、販売チャネル）を入力
3. `landingPageRepository.save()` でデータを保存
4. 保存成功後、作成したページの詳細画面へ遷移

### 2-ランディングページ編集

既存のランディングページを選択して編集。

**処理フロー**:
1. `landingPageRepository.get()` でランディングページデータを取得
2. フォームに現在の値を表示
3. 値を変更して保存ボタンをクリック
4. `landingPageRepository.save()` でデータを更新

### 3-CMSレイアウト割当

CMSレイアウトを選択してランディングページに適用。

**処理フロー**:
1. レイアウト選択モーダルを表示
2. 利用可能なCMSページ一覧から選択
3. `cmsPageId` を更新
4. 保存時にレイアウトが適用される

### 4-SEO設定

SEO関連の設定を行う。

**処理フロー**:
1. SEOタブに切り替え
2. メタタイトル、メタディスクリプション、キーワードを入力
3. SEO URLを設定（自動生成または手動入力）
4. 保存時にSEO設定が反映される

### 5-ランディングページ削除

不要なランディングページを削除。

**処理フロー**:
1. 削除確認モーダルを表示
2. 確定時、`landingPageRepository.delete()` を実行
3. 成功後、一覧に戻る

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ランディングページ取得 | landing_page | SELECT | ランディングページデータの取得 |
| ランディングページ作成 | landing_page, landing_page_sales_channel | INSERT | 新規作成 |
| ランディングページ更新 | landing_page | UPDATE | 情報の更新 |
| ランディングページ削除 | landing_page | DELETE | 削除 |
| SEO URL設定 | seo_url | INSERT/UPDATE | SEO URLの設定 |

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

#### landing_page

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | id指定 | 関連テーブル含む |
| INSERT | name, active, url, meta_title, meta_description, keywords, cms_page_id | 入力値 | 新規作成時 |
| UPDATE | name, active, url, meta_title, meta_description, keywords, cms_page_id | 入力値 | 更新時 |
| DELETE | - | id指定 | 削除時 |

#### landing_page_sales_channel

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | landing_page_id, sales_channel_id | 選択された販売チャネル | 新規作成・更新時 |
| DELETE | - | landing_page_id指定 | 販売チャネル解除時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| sw-landing-page.notification.saveSuccess | 成功 | 保存しました | 保存成功時 |
| sw-landing-page.notification.saveError | エラー | 保存に失敗しました | 保存失敗時 |
| sw-landing-page.notification.deleteSuccess | 成功 | 削除しました | 削除成功時 |

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| 必須項目未入力 | バリデーションエラーを表示 |
| URL重複 | エラー通知を表示 |
| 保存失敗 | エラー通知を表示、変更は破棄されない |
| 削除失敗 | エラー通知を表示 |

## 備考

- ランディングページモジュールはsw-landing-pageとして登録されているが、実際のUIはsw-category-detailコンポーネントを使用
- カテゴリとランディングページは同一のツリー構造で管理されるが、タイプで区別される
- SEO URLはseo_urlテーブルで管理され、販売チャネルごとに異なるURLを設定可能
- CMSレイアウトは `landingpage` タイプのCMSページのみ選択可能

---

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

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

### 推奨読解順序

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

ランディングページエンティティの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LandingPageDefinition | `src/Core/Content/LandingPage/LandingPageDefinition.php` | エンティティの定義 |
| 1-2 | LandingPageSalesChannelDefinition | `src/Core/Content/LandingPage/Aggregate/LandingPageSalesChannel/LandingPageSalesChannelDefinition.php` | 販売チャネルとの関連 |

**読解のコツ**: LandingPageはCmsPageと関連し、複数のSalesChannelに紐付く。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-landing-page/index.js` | モジュール登録 |

**主要処理フロー**:
1. **9-31行**: `Module.register('sw-landing-page', ...)` でモジュールを登録
2. **20-28行**: ルート定義（sw.category.detail.baseへリダイレクト）

#### Step 3: カテゴリ管理画面との関係を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sw-category-detail | `src/Administration/Resources/app/administration/src/module/sw-category/page/sw-category-detail/index.js` | 詳細画面コンポーネント |

**読解のコツ**: ランディングページの編集UIはカテゴリ管理画面と共通であり、sw-category-detailでランディングページタイプの処理も行われる。

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

```
sw-landing-page Module
    │
    └─ routes.index
           │
           └─ リダイレクト: sw.category.detail.base
                  │
                  └─ sw-category-detail Component
                         │
                         ├─ ランディングページ取得
                         │      └─ landingPageRepository.get()
                         │
                         ├─ ランディングページ保存
                         │      └─ landingPageRepository.save()
                         │
                         └─ ランディングページ削除
                                └─ landingPageRepository.delete()
```

### データフロー図

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

ランディングページID ──────▶ sw-category-detail Component
                                   │
                                   ├──▶ landingPageRepository.get()
                                   │         │
                                   │         ▼
                                   │    Shopware API
                                   │         │
                                   │         ▼
                                   └──▶ landingPage データ ──▶ 編集フォーム表示

フォーム入力値 ─────────────▶ sw-category-detail Component
                                   │
                                   ├──▶ landingPageRepository.save()
                                   │         │
                                   │         ▼
                                   │    Shopware API
                                   │         │
                                   │         ▼
                                   └──▶ 保存結果 ──▶ 成功/エラー通知
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-landing-page/index.js` | ソース | モジュール定義 |
| default-search-configuration.js | `src/Administration/Resources/app/administration/src/module/sw-landing-page/default-search-configuration.js` | ソース | 検索設定 |
| sw-category-detail | `src/Administration/Resources/app/administration/src/module/sw-category/page/sw-category-detail/` | ソース | 詳細画面（共通） |
| LandingPageDefinition.php | `src/Core/Content/LandingPage/LandingPageDefinition.php` | ソース | エンティティ定義 |
