# 画面設計書 34-タイムゾーン設定

## 概要

本ドキュメントは、Ghost管理画面の「タイムゾーン」設定の設計内容を記載した画面設計書です。この画面は、サイトのタイムゾーンを設定するための機能を提供します。

### 本画面の処理概要

この画面では、Ghostサイトで使用するタイムゾーンを選択・設定することができます。

**業務上の目的・背景**：投稿の公開日時、予約投稿、アナリティクスのタイムスタンプなど、時刻に関連するすべての機能がこのタイムゾーン設定に基づいて動作します。グローバルに展開するサイトや、読者の所在地と異なる場所からコンテンツを管理する場合に、適切なタイムゾーン設定が重要になります。

**画面へのアクセス方法**：
- 設定画面（/ghost/settings）のGeneral settingsセクション内
- 「Site timezone」項目でタイムゾーンを選択

**主要な操作・処理内容**：
1. 現在のタイムゾーンの確認：選択中のタイムゾーンと現地時刻を確認
2. タイムゾーンの選択：ドロップダウンから新しいタイムゾーンを検索・選択
3. 設定の保存：変更内容をAPIを通じて保存

**画面遷移**：
- 遷移元：設定画面のGeneral settingsセクション
- 遷移先：なし（インライン編集のため画面遷移なし）

**権限による表示制御**：Admin権限以上のスタッフユーザーのみ編集可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | 一般設定 | 主機能 | サイトのタイムゾーン設定 |

## 画面種別

編集（インライン選択形式）

## URL/ルーティング

| URL パターン | 説明 |
|-------------|------|
| `/ghost/settings` (General settings内) | 設定画面内のSite timezoneセクション |

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 選択肢 | 説明 |
|--------|-----|------|--------|------|
| Site timezone | String | Yes | @tryghost/timezone-dataより | タイムゾーン識別子（例: Asia/Tokyo） |

## 表示項目

### タイムゾーン選択

| 項目名 | コンポーネント | データソース | 説明 |
|--------|--------------|-------------|------|
| タイムゾーン選択 | Select (検索可能) | @tryghost/timezone-data | タイムゾーン一覧 |
| 現地時刻 | Hint (動的更新) | getLocalTime(timezone) | 1秒ごとに更新される現地時刻 |

## イベント仕様

### 1-タイムゾーン選択

**トリガー**: Selectコンポーネントでタイムゾーンを選択

**処理内容**:
- handleTimezoneChange(value)が呼ばれる
- updateSetting('timezone', value)でローカル設定を更新
- handleEditingChange(true)で編集状態に遷移
- Saveボタンが表示される

### 2-現地時刻の動的更新

**トリガー**: 毎秒（setIntervalで1000ms間隔）

**処理内容**:
- Hintコンポーネント内でuseEffectを使用
- getLocalTime(timezone)で現在時刻を取得
- UIに「The local time here is currently {currentTime}」を表示
- コンポーネントのアンマウント時にclearIntervalで停止

### 3-保存ボタンクリック

**トリガー**: Saveボタンをクリック

**処理内容**:
- handleSave()でAPI呼び出し
- 成功時: saveStateを更新

**API呼び出し**:
```
PUT /ghost/api/admin/settings/
Content-Type: application/json

{
  "settings": [
    { "key": "timezone", "value": "{選択されたタイムゾーン}" }
  ]
}
```

### 4-キャンセルボタンクリック

**トリガー**: Cancelボタンをクリック

**処理内容**:
- ローカル設定を元の値にリセット
- isEditingをfalseに変更

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示時 | settings | SELECT | 現在のtimezone取得 |
| 保存ボタンクリック | settings | UPDATE | timezoneの更新 |

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

#### settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | timezone | 選択されたタイムゾーン識別子 | キー: 'timezone' |

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|--------------|---------------|---------|
| ヒント（動的） | The local time here is currently {currentTime} | 常時表示、1秒ごとに更新 |

## 例外処理

| 例外状態 | 処理内容 |
|---------|---------|
| API通信エラー | エラートースト表示 |
| タイムゾーンデータロード失敗 | デフォルト選択肢で表示 |

## 備考

- タイムゾーンデータは@tryghost/timezone-dataパッケージから提供されます
- 編集ボタン（Edit）は非表示（hideEditButton={true}）で、Selectを直接操作して編集開始
- 現地時刻は選択中のタイムゾーンに基づいてリアルタイム更新されます
- withErrorBoundaryでコンポーネントエラーをキャッチします

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | timezone-data | `@tryghost/timezone-data` | タイムゾーンデータの構造（name, label） |

**読解のコツ**: timezoneDataはname（識別子）とlabel（表示名）を持つオブジェクトの配列。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | time-zone.tsx | `apps/admin-x-settings/src/components/settings/general/time-zone.tsx` | メインコンポーネント全体の構造 |

**主要処理フロー**:
1. **L3**: @tryghost/timezone-dataをインポート
2. **L18-35**: Hintコンポーネントで現地時刻をリアルタイム表示
3. **L37-46**: useSettingGroupフックでフォーム状態管理
4. **L48**: getSettingValuesで'timezone'を取得
5. **L50-55**: timezoneOptionsを生成（value/labelの形式に変換）
6. **L57-60**: handleTimezoneChangeでタイムゾーン変更処理
7. **L77-85**: Selectコンポーネントで検索可能なドロップダウンを表示

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | helpers.ts | `apps/admin-x-settings/src/utils/helpers.ts` | getLocalTime関数の実装 |

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

```
[ユーザー操作]
    │
    ├─ TimeZone コンポーネント
    │      │
    │      ├─ useSettingGroup() フック
    │      │      ├─ localSettings (ローカル設定状態)
    │      │      ├─ updateSetting() (設定値更新)
    │      │      └─ handleSave() (保存処理)
    │      │
    │      ├─ timezoneData.map()
    │      │      └─ timezoneOptions配列を生成
    │      │
    │      ├─ Hint コンポーネント
    │      │      ├─ useEffect (setInterval)
    │      │      └─ getLocalTime(timezone)
    │      │
    │      └─ TopLevelGroup
    │             └─ Select (isSearchable)
    │
    └─ [保存時]
           └─ Ghost Admin API
                  └─ PUT /settings/
```

### データフロー図

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

                     ┌─────────────────────────────┐
settings API ───────▶│ useSettingGroup()           │
(timezone)           │   - localSettingsにコピー   │
                     └────────────┬────────────────┘
                                  │
timezoneData ───────▶┌────────────▼────────────────┐
                     │ timezoneOptions.map()       │
                     │   - value/label形式に変換   │
                     └────────────┬────────────────┘
                                  │
                     ┌────────────▼────────────────┐
[Select選択] ───────▶│ handleTimezoneChange()      │
                     │   - updateSetting('timezone')│
                     │   - handleEditingChange(true)│
                     └────────────┬────────────────┘
                                  │
                     ┌────────────▼────────────────┐
                     │ Hint コンポーネント          │───▶ [現地時刻表示]
                     │   - setInterval(1000ms)      │     (リアルタイム更新)
                     │   - getLocalTime()           │
                     └─────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| time-zone.tsx | `apps/admin-x-settings/src/components/settings/general/time-zone.tsx` | ソース | メインコンポーネント |
| timezone-data | `@tryghost/timezone-data` | 外部パッケージ | タイムゾーンデータ |
| helpers.ts | `apps/admin-x-settings/src/utils/helpers.ts` | ソース | getLocalTime関数 |
| use-setting-group.ts | `apps/admin-x-settings/src/hooks/use-setting-group.ts` | ソース | 設定グループ管理フック |
| general-settings.tsx | `apps/admin-x-settings/src/components/settings/general/general-settings.tsx` | ソース | 親コンポーネント |
