# 画面設計書 41-テーマ変更

## 概要

本ドキュメントは、Ghost管理画面の「テーマ変更」設定画面の設計仕様を定義する。この画面はサイトのビジュアルデザインを決定するテーマの選択・インストール・切り替えを行う機能を提供する。

### 本画面の処理概要

この画面では、サイトの外観を制御するテーマの管理を行う。公式テーマの閲覧・選択、カスタムテーマのアップロード、テーマの有効化・削除などの操作が可能である。

**業務上の目的・背景**：Ghostサイトの外観はテーマによって決定される。サイト運営者がブランドやコンテンツに適したデザインを適用するため、テーマの選択・変更機能が必要である。公式テーマの提供により、技術的知識がなくてもプロフェッショナルなデザインを適用でき、カスタムテーマのアップロードにより、独自のブランディングも実現できる。

**画面へのアクセス方法**：管理画面のサイドバーから「Settings」→「Site」セクション→「Theme」カードの「Change theme」ボタンをクリックしてアクセスする。URLは`/ghost/#/settings/design/change-theme`となる。

**主要な操作・処理内容**：
1. 現在アクティブなテーマの確認（テーマ名とバージョン表示）
2. 「Change theme」ボタンによるテーマ選択モーダルの表示
3. 公式テーマ一覧の閲覧とプレビュー
4. テーマのインストール・有効化
5. ZIPファイルによるカスタムテーマのアップロード
6. インストール済みテーマの削除

**画面遷移**：設定画面（Site設定セクション）から遷移し、テーマ選択・プレビューモーダルが表示される。テーマインストール完了後は設定画面に戻る。Ghost Marketplaceへの外部リンクも提供される。

**権限による表示制御**：Administrator以上のロールを持つユーザーのみがテーマ変更機能にアクセスできる。Ghost(Pro)プランでは、テーマ数に制限がある場合があり、制限に達した場合はLimitModalが表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | テーマ管理 | 主機能 | サイトテーマの選択・アップロード・切り替え |
| 31 | カスタムテーマ設定 | 補助機能 | テーマ固有の設定変更 |

## 画面種別

設定画面（モーダル遷移型）

## URL/ルーティング

- メイン画面: `/ghost/#/settings` (navid: `theme`)
- テーマ選択モーダル: `/ghost/#/settings/design/change-theme`

## 入出力項目

| 項目名 | 種別 | データ型 | 必須 | 説明 |
|--------|------|---------|------|------|
| テーマファイル | 入力 | File (ZIP) | - | カスタムテーマアップロード時のZIPファイル |
| テーマ名 | 出力 | string | - | 選択されたテーマの名前 |
| バージョン | 出力 | string | - | テーマのバージョン番号 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| Active theme | string | 現在有効なテーマ名とバージョン（例：Source (v1.0)） |
| Theme list | Theme[] | 公式テーマ一覧（名前、カテゴリ、プレビュー画像） |
| Theme variants | ThemeVariant[] | テーマのバリエーション（カテゴリ別プレビュー） |

## イベント仕様

### 1-Change themeボタン押下

「Change theme」ボタンをクリックすると、以下の処理が実行される：

1. テーマ変更制限のチェック（`checkThemeLimitError`）
2. 制限エラーがある場合、`LimitModal`を表示しProプランへの誘導
3. 制限がない場合、`design/change-theme`ルートへ遷移しテーマ選択モーダルを表示

### 2-テーマ選択

公式テーマ一覧からテーマをクリックすると：

1. `ThemePreview`コンポーネントが表示される
2. デスクトップ/モバイルプレビューの切り替えが可能
3. テーマにバリアントがある場合、ドロップダウンで切り替え可能

### 3-テーマインストール

「Install」ボタンをクリックすると：

1. `useInstallTheme`フックを通じてAPIリクエストを送信
2. GitHubから公式テーマをインストール
3. インストール完了後、`ThemeInstalledModal`で結果を表示
4. GScanによるテーマ検証エラー/警告がある場合は表示

### 4-テーマアップロード

ZIPファイルをアップロードすると：

1. `useUploadTheme`フックを通じてAPIリクエストを送信
2. アップロードされたテーマをサーバーで検証
3. 検証結果に応じて成功/エラーモーダルを表示

### 5-テーマ有効化

「Activate」ボタンをクリックすると：

1. `useActivateTheme`フックを通じてAPIリクエストを送信
2. 選択されたテーマをアクティブ化
3. カスタムテーマ設定のキャッシュを無効化

### 6-テーマ削除

削除ボタンをクリックすると：

1. 確認モーダルを表示
2. 確認後、`useDeleteTheme`フックを通じてAPIリクエストを送信
3. デフォルトテーマ（Source, Casper）とアクティブテーマは削除不可

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| テーマインストール | settings | UPDATE | active_theme設定の更新 |
| テーマ有効化 | settings | UPDATE | active_theme設定の更新 |
| テーマ削除 | - | DELETE | ファイルシステムからテーマを削除 |

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

#### settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | key='active_theme' | 選択されたテーマ名 | テーマ有効化時 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|-----------|----------|
| 成功 | Theme installed successfully | テーマインストール完了時 |
| 成功 | Theme activated | テーマ有効化完了時 |
| 警告 | GScan warnings | テーマにGScan警告がある場合 |
| エラー | GScan errors | テーマにGScanエラーがある場合 |
| エラー | Theme limit reached | プラン制限に達した場合 |
| 確認 | Are you sure you want to delete this theme? | テーマ削除時 |

## 例外処理

| 状態 | 処理内容 |
|------|----------|
| テーマ制限エラー | LimitModalを表示し、Proプランへの誘導リンクを表示 |
| アップロードエラー | InvalidThemeModalでエラー内容を表示 |
| ネットワークエラー | エラートーストを表示 |
| 削除不可テーマ | デフォルト/アクティブテーマは削除ボタンが無効化 |

## 備考

- デフォルトテーマ「Source」と旧デフォルトテーマ「Casper」は削除不可
- テーマのインストール元はGitHub
- Ghost Marketplaceで有料テーマの購入が可能（外部リンク）
- テーマプレビューはiframeで外部URLを読み込む
- テーマバリアントは3秒間隔で自動ループ表示

---

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

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

### 推奨読解順序

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

まず、テーマに関連するデータ型定義を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | themes.ts | `apps/admin-x-framework/src/api/themes.ts` | Theme型、InstalledTheme型、ThemeProblem型の定義（1-36行目） |

**読解のコツ**: TypeScriptの型定義を理解することで、APIレスポンスの構造とUIでの表示項目の関係が明確になる。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | change-theme.tsx | `apps/admin-x-settings/src/components/settings/site/change-theme.tsx` | メインコンポーネントの構造（9-68行目） |

**主要処理フロー**:
1. **14行目**: `useBrowseThemes`でテーマ一覧を取得
2. **15行目**: `activeTheme`でアクティブテーマを特定
3. **17-26行目**: `useEffect`でテーマ変更制限をチェック
4. **28-42行目**: `openPreviewModal`でモーダル表示ロジック

#### Step 3: テーマ選択UIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | official-themes.tsx | `apps/admin-x-settings/src/components/settings/site/theme/official-themes.tsx` | 公式テーマ一覧の表示ロジック |
| 3-2 | theme-preview.tsx | `apps/admin-x-settings/src/components/settings/site/theme/theme-preview.tsx` | テーマプレビューとインストールボタン |

**主要処理フロー**:
- **official-themes.tsx 25-29行目**: テーマ選択時のコールバック
- **theme-preview.tsx 62-75行目**: インストールボタンのラベル制御

#### Step 4: APIフックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | themes.ts | `apps/admin-x-framework/src/api/themes.ts` | 全APIフックの定義（50-135行目） |

**主要処理フロー**:
- **50-53行目**: `useBrowseThemes` - テーマ一覧取得
- **60-82行目**: `useActivateTheme` - テーマ有効化
- **97-113行目**: `useInstallTheme` - GitHubからインストール
- **115-135行目**: `useUploadTheme` - ZIPアップロード

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

```
ChangeTheme (change-theme.tsx)
    │
    ├─ useBrowseThemes() ──────────► GET /themes/
    │
    ├─ useCheckThemeLimitError()
    │      └─ useLimiter()
    │
    └─ openPreviewModal()
           │
           └─ updateRoute('design/change-theme')
                  │
                  ├─ OfficialThemes (official-themes.tsx)
                  │      └─ useOfficialThemes()
                  │
                  └─ ThemePreview (theme-preview.tsx)
                         │
                         ├─ useActivateTheme() ──► PUT /themes/{name}/activate/
                         ├─ useInstallTheme() ───► POST /themes/install/
                         └─ useUploadTheme() ────► POST /themes/upload/
```

### データフロー図

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

                    ┌─────────────────┐
                    │  useBrowseThemes │
                    └────────┬────────┘
                             │
ユーザー操作 ────────────────┼───────────────────────► テーマ一覧表示
                             │
                    ┌────────▼────────┐
                    │ OfficialThemes   │
テーマ選択 ─────────┤                  ├─────────────► プレビュー表示
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
Install/Activate ───┤  ThemePreview    │
                    └────────┬────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
     ┌────────▼────┐  ┌──────▼─────┐  ┌────▼────────┐
     │ActivateTheme│  │InstallTheme│  │UploadTheme  │
     └──────┬──────┘  └──────┬─────┘  └──────┬──────┘
            │                │               │
            └────────────────┼───────────────┘
                             │
                    ┌────────▼────────┐
                    │   settings DB    │
                    │ (active_theme)   │
                    └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| change-theme.tsx | `apps/admin-x-settings/src/components/settings/site/change-theme.tsx` | ソース | メイン設定カードコンポーネント |
| official-themes.tsx | `apps/admin-x-settings/src/components/settings/site/theme/official-themes.tsx` | ソース | 公式テーマ一覧表示 |
| theme-preview.tsx | `apps/admin-x-settings/src/components/settings/site/theme/theme-preview.tsx` | ソース | テーマプレビュー表示 |
| theme-installed-modal.tsx | `apps/admin-x-settings/src/components/settings/site/theme/theme-installed-modal.tsx` | ソース | インストール完了モーダル |
| invalid-theme-modal.tsx | `apps/admin-x-settings/src/components/settings/site/theme/invalid-theme-modal.tsx` | ソース | テーマエラーモーダル |
| advanced-theme-settings.tsx | `apps/admin-x-settings/src/components/settings/site/theme/advanced-theme-settings.tsx` | ソース | テーマ詳細設定 |
| themes.ts | `apps/admin-x-framework/src/api/themes.ts` | ソース | テーマAPI定義 |
| use-check-theme-limit-error.ts | `apps/admin-x-settings/src/hooks/use-check-theme-limit-error.ts` | ソース | テーマ制限チェックフック |
| settings-app-provider.tsx | `apps/admin-x-settings/src/components/providers/settings-app-provider.tsx` | ソース | 公式テーマデータプロバイダー |
