# 画面設計書 13-口座一覧画面（モバイル）

## 概要

本ドキュメントは、Actual Budgetアプリケーションにおけるモバイル向け口座一覧画面の設計仕様を定義する。

### 本画面の処理概要

口座一覧画面（モバイル）は、ユーザーが保有するすべての口座を一覧表示し、各口座の残高を確認できるモバイル最適化画面である。口座は「On Budget（予算内）」「Off Budget（予算外）」「Closed（クローズ済み）」のグループに分類して表示される。

**業務上の目的・背景**：モバイルデバイスから手軽に資産状況を確認したいというニーズに応える画面である。シンプルな一覧形式で全口座の残高を俯瞰でき、個別口座への素早いアクセスを提供する。ドラッグ&ドロップによる口座の並び替えもサポートし、ユーザーの使いやすさを優先した口座順序のカスタマイズが可能。

**画面へのアクセス方法**：モバイルナビゲーションの「口座」タブをタップしてアクセスする。URLパターンは `/accounts` である。

**主要な操作・処理内容**：
1. 全口座の一覧表示（グループ分け：On Budget / Off Budget / Closed）
2. 各口座残高の表示
3. 口座追加モーダルの呼び出し
4. 特定口座の詳細画面への遷移
5. 口座の並び替え（ドラッグ&ドロップ）
6. プルトゥリフレッシュによる同期
7. クローズ済み口座の表示/非表示切り替え

**画面遷移**：
- 遷移元：モバイルナビゲーション、予算画面（モバイル）
- 遷移先：口座詳細画面（モバイル）、口座追加モーダル

**権限による表示制御**：特になし。認証済みユーザーであれば全機能を利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 口座作成・編集・削除 | 補助機能 | モバイルでの口座管理 |
| 6 | 口座残高管理 | 主機能 | モバイルでの口座残高表示 |
| 60 | レスポンシブUI | 補助機能 | モバイル最適化表示 |

## 画面種別

一覧

## URL/ルーティング

`/accounts`

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | 型 | 必須 | 説明 |
|--------|--------|----------|-----|------|------|
| なし | - | - | - | - | 本画面は入力パラメータを受け取らない |

## 表示項目

| 項目名 | 説明 | データソース |
|--------|------|-------------|
| ページタイトル | 「Accounts」固定 | i18n |
| 全口座残高 | すべての口座の残高合計 | allAccountBalance binding |
| On Budget残高 | 予算内口座の残高合計 | onBudgetAccountBalance binding |
| Off Budget残高 | 予算外口座の残高合計 | offBudgetAccountBalance binding |
| Closed残高 | クローズ済み口座の残高合計 | closedAccountBalance binding |
| 口座リスト | 各口座の名前と残高 | accounts |

### 口座リスト項目

| 項目名 | 説明 | 表示条件 |
|--------|------|---------|
| 同期ステータスインジケータ | 銀行連携口座の同期状態を示す色付き丸 | bankIdが設定されている場合 |
| 口座名 | 口座の名前 | 常に表示 |
| 口座残高 | 口座の現在残高（正負で色分け） | 常に表示 |

## イベント仕様

### 1-口座追加ボタン押下

ヘッダー右側の「+」ボタンを押下すると、add-accountモーダルが表示される。

### 2-口座グループヘッダータップ

「All accounts」「On budget」「Off budget」などのグループヘッダーをタップすると、該当グループの取引一覧画面に遷移する。

### 3-クローズ済み口座ヘッダータップ

「Closed」グループヘッダーをタップすると、クローズ済み口座の表示/非表示が切り替わる。表示状態はローカル設定（ui.showClosedAccounts）に保存される。

### 4-口座項目タップ

個別の口座項目をタップすると、該当口座の詳細画面（`/accounts/:accountId`）に遷移する。

### 5-プルトゥリフレッシュ

画面を下方向にプルすると、syncAndDownloadアクションが実行され、銀行同期が行われる。

### 6-口座ドラッグ&ドロップ

口座項目を長押しして上下にドラッグすることで、同一グループ内での口座順序を変更できる。moveAccountアクションが実行される。

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

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

本画面は主に参照機能であり、口座順序変更のみがデータベースを更新する。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | accounts | SELECT | 全口座情報を取得 |
| 口座並び替え | accounts | UPDATE | sort_order を更新 |
| プルトゥリフレッシュ | transactions | INSERT/UPDATE | 同期による取引追加・更新 |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sort_order | 移動後の順序 | moveAccountアクション経由 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| M001 | 情報 | For Actual to be useful, you need to add an account. You can link an account to automatically download transactions, or manage it locally yourself. | 口座が0件の場合 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 口座データなし | EmptyMessageコンポーネントで口座追加を促すメッセージを表示 |
| 同期エラー | 同期失敗口座は赤いインジケータで表示 |

## 備考

- 数値フォーマット（numberFormat）または小数表示設定（hideFraction）が変更された場合、コンポーネント全体が再レンダリングされる（keyプロパティによる強制再レンダリング）
- 口座リストはreact-aria-componentsのListBoxを使用
- ドラッグ&ドロップはuseDragAndDropフックで実装
- 残高の表示色は正（緑）、負（赤）、ゼロ（グレー）で色分け

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models/index.d.ts | `packages/loot-core/types/models/` | AccountEntityの型定義（offbudget, closed, bankIdフィールド） |

**読解のコツ**: offbudget=0/1でOn/Off Budget、closed=0/1でアクティブ/クローズを判定。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AccountsPage.tsx | `packages/desktop-client/src/components/mobile/accounts/AccountsPage.tsx` | メインコンポーネント |

**主要処理フロー**:
1. **行516-522**: useSyncedPrefで数値フォーマット設定取得
2. **行525-530**: onOpenAccountコールバック - 口座詳細への遷移
3. **行532-534**: onAddAccountコールバック - モーダル呼び出し
4. **行536-538**: onSyncコールバック - 同期実行
5. **行540-556**: AllAccountListレンダリング

#### Step 3: 口座リストコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AllAccountList | 同上（行272-392） | グループ分けと各セクションの表示 |

**主要処理フロー**:
- **行284-290**: 口座のフィルタリング（On Budget / Off Budget / Closed）
- **行293-309**: クローズ済み口座の表示切替ロジック
- **行336-388**: 各セクションのレンダリング（AccountHeader + AccountList）

#### Step 4: 個別口座リストを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AccountList | 同上（行403-511） | ドラッグ&ドロップ対応リスト |

**主要処理フロー**:
- **行420-480**: useDragAndDropフックの設定（getItems, renderDropIndicator, onReorder）
- **行496-508**: AccountListItemのレンダリング

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

```
AccountsPage (エントリーポイント)
    |
    +-- AllAccountList
            |
            +-- MobilePageHeader
            |       +-- 口座追加ボタン
            |
            +-- PullToRefresh (プルトゥリフレッシュ)
            |
            +-- AccountHeader (All accounts)
            +-- AccountHeader (On budget)
            +-- AccountList (On budget accounts)
            |       +-- AccountListItem (各口座)
            |
            +-- AccountHeader (Off budget)
            +-- AccountList (Off budget accounts)
            |       +-- AccountListItem (各口座)
            |
            +-- AccountHeader (Closed)
            +-- AccountList (Closed accounts) [条件付き]
                    +-- AccountListItem (各口座)
```

### データフロー図

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

accounts store    --->  useAccounts                --->  accounts array
                        (口座フック)

Redux state       --->  useSelector                --->  syncingAccountIds
(account.accountsSyncing) (同期状態取得)                   updatedAccounts

Redux state       --->  useFailedAccounts          --->  failedAccounts Map
(failed accounts)       (失敗口座取得)

spreadsheet       --->  bindings.*Balance          --->  各種残高表示
                        (残高バインディング)

User action       --->  syncAndDownload            --->  同期実行
(Pull to refresh)       (dispatch)

User action       --->  moveAccount                --->  口座順序更新
(Drag & drop)           (dispatch)

User action       --->  navigate                   --->  画面遷移
(Account tap)           (`/accounts/:id`)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AccountsPage.tsx | `packages/desktop-client/src/components/mobile/accounts/AccountsPage.tsx` | ソース | メインコンポーネント |
| MobilePageHeader.tsx | `packages/desktop-client/src/components/mobile/MobilePageHeader.tsx` | ソース | ページヘッダー |
| PullToRefresh.tsx | `packages/desktop-client/src/components/mobile/PullToRefresh.tsx` | ソース | プルトゥリフレッシュ |
| bindings.ts | `packages/desktop-client/src/spreadsheet/bindings.ts` | ソース | 残高バインディング定義 |
| accountsSlice.ts | `packages/desktop-client/src/accounts/accountsSlice.ts` | ソース | 口座Redux（moveAccount含む） |
| appSlice.ts | `packages/desktop-client/src/app/appSlice.ts` | ソース | syncAndDownloadアクション |
| useAccounts.ts | `packages/desktop-client/src/hooks/useAccounts.ts` | ソース | 口座データフック |
| useFailedAccounts.ts | `packages/desktop-client/src/hooks/useFailedAccounts.ts` | ソース | 失敗口座フック |
