# 画面設計書 8-予算ファイル選択画面

## 概要

本ドキュメントは、Actual Budget アプリケーションの予算ファイル選択画面の設計仕様を記述したものである。

### 本画面の処理概要

予算ファイル選択画面は、認証済みユーザーが既存の予算ファイルを選択・管理するための画面である。ローカルファイル、クラウド同期ファイル、リモートファイルの一覧を表示し、予算ファイルのオープン、削除、複製、インポート、新規作成を行うことができる。

**業務上の目的・背景**：Actual Budget では複数の予算ファイルを管理できるため、ユーザーは用途に応じた複数の予算（個人用、家計用、プロジェクト用など）を切り替えて使用できる。この画面は予算ファイルのハブとして機能し、クラウド同期状態の確認、マルチユーザー環境でのファイル共有状況の表示、ファイル管理操作を提供する。

**画面へのアクセス方法**：以下の条件でこの画面に遷移する：
- 認証済みで、予算ファイルが1件以上存在する状態でルート画面（`/`）にアクセス
- 予算画面のメニューから「Switch budget file」を選択
- 設定画面から「Close file」を選択

**主要な操作・処理内容**：
1. 予算ファイルの選択・オープン（ローカル/リモート）
2. 予算ファイルの削除
3. 予算ファイルの複製
4. 予算ファイルのインポート
5. 新規予算ファイルの作成
6. ファイル一覧の更新（リフレッシュ）
7. ファイル設定の表示（Electron）

**画面遷移**：
- 遷移元：ログイン完了後、予算画面からの切り替え、設定画面からのファイルクローズ
- 遷移先：予算画面（`/budget`）（予算ファイル選択後）

**権限による表示制御**：マルチユーザー環境では、ファイルオーナーとアクセス権を持つユーザーの情報が表示される。自分がオーナーでないファイルには「Owner: xxx」が表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | クラウド同期 | 主機能 | 既存予算ファイルの一覧表示・選択処理 |
| 45 | バックアップ管理 | 補助機能 | 予算ファイルのバックアップ状態確認 |

## 画面種別

一覧画面

## URL/ルーティング

`/`（予算ファイルが1件以上存在する場合に表示）

## 入出力項目

| 項目名 | 項目ID | 入出力 | 必須 | データ型 | 最大長 | 備考 |
|--------|--------|--------|------|----------|--------|------|
| - | - | - | - | - | - | 入力項目なし（選択操作のみ） |

## 表示項目

| 項目名 | 表示内容 | 備考 |
|--------|----------|------|
| タイトル | "Files" | 固定テキスト |
| ファイル一覧 | 予算ファイルのリスト | GridListコンポーネント |
| ファイル名 | 各ファイルの名前 | 太字表示 |
| ファイル状態 | Local / Syncing / Available for download / Network unavailable | アイコンとテキスト |
| オーナー情報 | "Owner: xxx" | マルチユーザー・自分がオーナーでない場合 |
| 共有ユーザー | ユーザーアイコンとツールチップ | マルチユーザー・共有時 |
| 暗号化アイコン | 鍵アイコン | 暗号化ファイルの場合 |

## イベント仕様

### 1-ファイル選択（ファイル行クリック/タップ）

1. ファイルの状態を確認
2. **ローカル/同期済みファイル**: `loadBudget` または `closeAndLoadBudget` を実行
3. **リモートファイル**: `downloadBudget` または `closeAndDownloadBudget` を実行
4. 予算画面（`/budget`）に遷移

### 2-ファイル削除（メニュー → Delete）

1. `pushModal` で削除確認モーダル（'delete-budget'）を表示
2. 確認後、ファイルを削除

### 3-ファイル複製（メニュー → Duplicate）

1. `pushModal` で複製モーダル（'duplicate-budget'）を表示
2. 新しいファイル名を入力して複製実行
3. ローカルファイルのみ複製可能

### 4-ファイルインポート（Import fileボタン押下）

1. `pushModal` でインポートモーダル（'import'）を表示
2. インポート形式を選択してファイルをインポート

### 5-新規ファイル作成（Create new fileボタン押下）

1. `createBudget` アクションを空オプションで実行
2. 空の予算ファイルが作成される
3. 予算画面に遷移

### 6-ファイル一覧更新（更新ボタン押下）

1. `getUserData` アクションを実行
2. `loadAllFiles` アクションを実行
3. ファイル一覧を最新状態に更新

### 7-ファイル設定（設定ボタン押下、Electron）

1. `pushModal` で設定モーダル（'files-settings'）を表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ファイル選択 | app_state（ローカル） | UPDATE | 現在開いているファイルIDを更新 |
| ファイル削除 | budgets, transactions等 | DELETE | 予算ファイルと関連データを削除 |
| ファイル複製 | budgets, transactions等 | INSERT | 予算ファイルと関連データを複製 |
| 新規作成 | budgets, categories | INSERT | 空の予算ファイルを作成 |

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

#### app_state（ローカル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | currentBudgetId | 選択されたファイルのID | 現在開いているファイル |

## メッセージ仕様

| メッセージID | メッセージ内容 | 種別 | 表示条件 |
|-------------|---------------|------|----------|
| no-files | "No budget files" | 情報 | ファイルが0件の場合（通常はWelcomeScreenが表示される） |

## 例外処理

| 例外ケース | 処理内容 |
|------------|----------|
| ファイルロード失敗 | エラー通知を表示 |
| ネットワーク未接続 | ファイル状態に「Network unavailable」を表示、リフレッシュボタン非表示 |
| 暗号化キーなし | 鍵アイコンをグレーアウト表示、ファイル説明に「do not have the key」を表示 |

## 備考

- ファイル状態は `local` / `synced` / `remote` / `unknown` / `broken` / `detached` のいずれか
- 現在開いているファイルは一覧から除外される（quickSwitchModeの場合）
- Electron環境では設定ボタンが追加表示
- サーバーがオフラインの場合、リフレッシュボタンは非表示

---

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

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

### 推奨読解順序

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

ファイル情報の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | file.d.ts | `loot-core/types/file.d.ts` | File, LocalFile, RemoteFile, SyncedLocalFile等の型定義 |

**読解のコツ**: `state` プロパティの値（local/synced/remote等）とそれぞれの意味を理解する

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

メインコンポーネントの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BudgetFileSelection.tsx | `packages/desktop-client/src/components/manager/BudgetFileSelection.tsx` | メインコンポーネントの実装 |

**主要処理フロー**:
1. **543-551行目**: BudgetFileSelection関数の初期化、props、状態管理
2. **555-567行目**: マルチユーザー環境でのユーザー情報取得
3. **577-579行目**: 現在開いているファイルを一覧から除外
4. **589-594行目**: onCreate関数で新規ファイル作成
5. **596-599行目**: refresh関数でファイル一覧更新
6. **606-619行目**: onSelect関数でファイル選択処理

#### Step 3: ファイルリスト表示を理解する

一覧表示コンポーネントを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BudgetFileList | `packages/desktop-client/src/components/manager/BudgetFileSelection.tsx` (394-442行目) | ファイルリストコンポーネント |
| 3-2 | BudgetFileListItem | `packages/desktop-client/src/components/manager/BudgetFileSelection.tsx` (285-383行目) | ファイル行コンポーネント |
| 3-3 | BudgetFileState | `packages/desktop-client/src/components/manager/BudgetFileSelection.tsx` (171-273行目) | ファイル状態表示コンポーネント |

#### Step 4: ファイル操作を理解する

Redux アクションとスライスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | budgetfilesSlice.ts | `packages/desktop-client/src/budgetfiles/budgetfilesSlice.ts` | loadBudget, downloadBudget, createBudget等のアクション |

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

```
BudgetFileSelection (BudgetFileSelection.tsx)
    │
    ├─ BudgetFileSelectionHeader
    │      ├─ RefreshButton
    │      │      └─ refresh() → getUserData() + loadAllFiles()
    │      │
    │      └─ SettingsButton (Electron)
    │             └─ pushModal({ modal: { name: 'files-settings' } })
    │
    ├─ BudgetFileList
    │      └─ BudgetFileListItem (各ファイル)
    │             ├─ BudgetFileState (状態表示)
    │             ├─ UserAccessForFile (共有ユーザー表示)
    │             ├─ BudgetFileMenuButton
    │             │      └─ BudgetFileMenu
    │             │             ├─ onDelete → pushModal('delete-budget')
    │             │             └─ onDuplicate → pushModal('duplicate-budget')
    │             │
    │             └─ onSelect(file)
    │                    ├─ [remote] → downloadBudget / closeAndDownloadBudget
    │                    └─ [local/synced] → loadBudget / closeAndLoadBudget
    │
    ├─ "Import file" ボタン
    │      └─ pushModal({ modal: { name: 'import' } })
    │
    └─ "Create new file" ボタン
           └─ createBudget({})
```

### データフロー図

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

                    BudgetFileSelection表示
                              │
                              ▼
               useSelector(state.budgetfiles.allFiles)
                              │
                              ▼
                    ファイル一覧表示 ────────────────────▶ BudgetFileList
                              │
                              ▼
                    [ユーザー: ファイル選択]
                              │
          ┌───────────────────┴───────────────────┐
          ▼                                       ▼
   [ローカル/同期済み]                         [リモート]
          │                                       │
          ▼                                       ▼
   loadBudget(id)                     downloadBudget(cloudFileId)
          │                                       │
          └───────────────────┬───────────────────┘
                              ▼
                    Redux state 更新
                              │
                              ▼
                    予算画面 (/budget) へ遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BudgetFileSelection.tsx | `packages/desktop-client/src/components/manager/BudgetFileSelection.tsx` | ソース | メインコンポーネント |
| ManagementApp.tsx | `packages/desktop-client/src/components/manager/ManagementApp.tsx` | ソース | ルーティング定義・表示条件 |
| budgetfilesSlice.ts | `packages/desktop-client/src/budgetfiles/budgetfilesSlice.ts` | ソース | ファイル操作アクション |
| usersSlice.ts | `packages/desktop-client/src/users/usersSlice.ts` | ソース | getUserData アクション |
| modalsSlice.ts | `packages/desktop-client/src/modals/modalsSlice.ts` | ソース | pushModal アクション |
| ServerContext.tsx | `packages/desktop-client/src/components/ServerContext.tsx` | ソース | useMultiuserEnabled hook |
| file.d.ts | `loot-core/types/file.d.ts` | 型定義 | ファイル型定義 |
