# 機能設計書 64-コマンドバー

## 概要

本ドキュメントは、Actualアプリケーションにおけるコマンドバー機能の設計仕様を記載したものである。キーボードショートカットで機能に素早くアクセスするコマンドパレット機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：家計簿アプリケーションでは、予算、口座、レポートなど複数の画面を頻繁に行き来する必要がある。コマンドバーは、キーボードショートカット（Cmd/Ctrl+K）で即座に検索可能なコマンドパレットを表示し、マウス操作なしで目的の画面や機能に素早くアクセスできるようにする。生産性向上とキーボード中心のワークフローを支援する。

**機能の利用シーン**：
- 予算画面から口座詳細にすぐに移動したい場合
- 特定の口座残高をすぐに確認したい場合
- カスタムレポートに素早くアクセスしたい場合
- 設定画面やルール管理画面に移動したい場合

**主要な処理内容**：
1. キーボードショートカット（Cmd/Ctrl+K）の検知
2. コマンドパレットダイアログの表示
3. 検索入力による項目フィルタリング
4. ナビゲーション項目（Budget, Reports, Schedules等）の表示
5. 口座一覧と残高の表示
6. カスタムレポート一覧の表示
7. 選択した項目への画面遷移

**関連システム・外部連携**：
- cmdk（コマンドパレットライブラリ）
- React Router（ナビゲーション）
- スプレッドシート機能（残高取得）

**権限による制御**：特別な権限制御はなく、予算ファイルにアクセス可能なユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面共通 | オーバーレイ | キーボードショートカットでどの画面からでもアクセス可能 |

## 機能種別

ナビゲーション / UI支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| search | string | No | 検索クエリ | - |
| keyboardEvent | KeyboardEvent | Yes | キーボードイベント | Cmd/Ctrl+K |

### 入力データソース

- キーボードイベント（document.addEventListener）
- useAccounts Hook（口座一覧）
- useReports Hook（カスタムレポート一覧）
- useMetadataPref（予算名）
- useModalState（モーダル状態）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| navigation | void | 選択した項目への画面遷移 |

### 出力先

- 画面遷移（React Router navigate）

## 処理フロー

### 処理シーケンス

```
1. キーボードショートカット検知（Cmd/Ctrl+K）
   └─ openEventListener関数で検知

2. モーダルが開いていないか確認
   └─ modalStack.length > 0の場合は開かない

3. Command.Dialog表示
   └─ open状態をtrueに設定

4. 検索入力
   └─ Command.Inputで検索クエリを入力

5. 項目フィルタリング
   └─ 検索クエリで各セクションの項目をフィルタ

6. 項目選択
   └─ Command.Itemのクリックまたはキーボード選択

7. 画面遷移
   └─ handleNavigate関数でnavigate実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{Cmd/Ctrl+K押下}
    B -->|Yes| C{モーダル開いている?}
    C -->|Yes| B
    C -->|No| D[Command.Dialog表示]
    D --> E{検索入力}
    E --> F[セクション別フィルタリング]
    F --> G{結果あり?}
    G -->|Yes| H[フィルタ結果表示]
    G -->|No| I[No results found表示]
    H --> J{項目選択}
    I --> J
    J -->|選択| K[handleNavigate実行]
    J -->|Escape/クリック外| L[ダイアログ閉じる]
    K --> M[navigate(path)]
    M --> L
    L --> N[search状態リセット]
    N --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-001 | モーダル排他制御 | モーダルが開いている状態ではコマンドバーを開かない | Cmd/Ctrl+K押下時 |
| BR-64-002 | 検索リセット | ダイアログを閉じるときに検索クエリをリセット | ダイアログ閉じる時 |
| BR-64-003 | 大文字小文字無視 | 検索は大文字小文字を区別しない | フィルタリング時 |
| BR-64-004 | クローズ口座除外 | クローズされた口座は表示しない | 口座セクション表示時 |
| BR-64-005 | Vim風キーバインド | Cmd+J/Kで上下移動可能 | vimBindings有効時 |

### 計算ロジック

- 口座残高: CellValueコンポーネントでスプレッドシートから取得
- フィルタリング: item.name.toLowerCase().includes(searchLower)

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 口座取得 | accounts | SELECT | 全口座情報の取得 |
| レポート取得 | custom_reports | SELECT | カスタムレポート一覧の取得 |
| 残高取得 | spreadsheet_cells | SELECT | 口座残高の取得 |

### テーブル別操作詳細

特にデータ更新はなし（参照のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 特別なエラー処理なし | - |

### リトライ仕様

特になし

## トランザクション仕様

データ参照のみのため、トランザクション管理は不要。

## パフォーマンス要件

- コマンドバー表示: 50ms以内
- 検索フィルタリング: 50ms以内（クライアントサイド処理）
- 画面遷移: 100ms以内

## セキュリティ考慮事項

- ユーザー入力は検索フィルタリングのみに使用
- XSS対策: Reactの標準的なエスケープ処理

## 備考

- cmdkライブラリ（cmdk）を使用
- z-index: 3001でモーダルの上に表示
- shouldFilter={false}でカスタムフィルタリングを使用

---

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

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

### 推奨読解順序

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

まず、コマンドバーで表示するアイテムの型定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CommandBar.tsx | `packages/desktop-client/src/components/CommandBar.tsx` | SearchableItem型、SearchSection型の定義（51-69行目） |

**読解のコツ**: SearchableItemはid, name, Icon, contentを持ち、SearchSectionはkey, heading, items, onSelectを持つ。セクション単位でナビゲーション項目、口座、カスタムレポートをグループ化している。

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

処理の起点となる関数を特定。

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

**主要処理フロー**:
1. **103-109行目**: useState、useNavigate等の初期化
2. **111-144行目**: navigationItems定義（useMemo）
3. **146-149行目**: useEffectでダイアログ閉じる時に検索リセット
4. **151-154行目**: useAccounts、useReportsでデータ取得
5. **156-166行目**: openEventListener定義（useCallback）
6. **168-171行目**: useEffectでkeydownイベント登録
7. **173-179行目**: handleNavigate定義（useCallback）
8. **181-239行目**: sections定義（ナビゲーション、口座、カスタムレポート）
9. **241-248行目**: フィルタリング処理
10. **250-374行目**: Command.Dialogのレンダリング

#### Step 3: コンポーネント構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CommandBar.tsx | `packages/desktop-client/src/components/CommandBar.tsx` | Command.Dialog、Command.Input、Command.List、Command.Group、Command.Itemの構造 |

**主要処理フロー（レンダリング）**:
- **251-272行目**: Command.Dialog - ダイアログ全体のラッパー
- **274-292行目**: Command.Input - 検索入力フィールド
- **293-306行目**: Command.List - 検索結果リストのラッパー
- **307-358行目**: Command.GroupとCommand.Itemのマッピング
- **360-371行目**: Command.Empty - 結果なし時の表示

#### Step 4: ヘルパーコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CommandBar.tsx | `packages/desktop-client/src/components/CommandBar.tsx` | BalanceRowコンポーネント（71-101行目） |

**主要処理フロー（BalanceRow）**:
- **71-80行目**: BalanceRowの型定義とプロップス
- **81-101行目**: CellValueコンポーネントで残高表示

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

```
CommandBar (メインコンポーネント)
    │
    ├─ useAccounts() ──────────────────┐
    │                                   │
    ├─ useReports() ────────────────────┤
    │                                   │
    ├─ useNavigate() ───────────────────┤
    │                                   │
    ├─ useMetadataPref('budgetName') ───┤
    │                                   │
    ├─ useModalState() ─────────────────┤
    │                                   │
    ├─ openEventListener               │
    │      └─ document.addEventListener('keydown')
    │                                   │
    ├─ handleNavigate                  │
    │      └─ navigate(path)           │
    │                                   │
    ├─ Command.Dialog (cmdk)           │
    │      │                           │
    │      ├─ Command.Input            │
    │      │                           │
    │      └─ Command.List             │
    │             │                    │
    │             ├─ Command.Group (Navigation)
    │             │      └─ Command.Item × N
    │             │                    │
    │             ├─ Command.Group (Accounts)
    │             │      └─ Command.Item × N
    │             │             └─ BalanceRow
    │             │                    └─ CellValue
    │             │                           └─ accountBalance binding
    │             │                    │
    │             └─ Command.Group (Custom Reports)
    │                    └─ Command.Item × N
    │
    └─ BalanceRow
           └─ CellValue
                  └─ CellValueText
```

### データフロー図

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

キーボードイベント ────┐
(Cmd/Ctrl+K)          │
                      ▼
              ┌─────────────────┐
              │ openEventListener│
              │ - preventDefault │
              │ - modalStack確認 │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ setOpen(true)   │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ Command.Dialog  │
              │ 表示            │
              └────────┬────────┘
                       │
        ┌──────────────┼──────────────┐
        │              │              │
        ▼              ▼              ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Navigation  │ │ Accounts    │ │ Custom      │
│ Items       │ │ + Balances  │ │ Reports     │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
       │               │               │
       └───────────────┼───────────────┘
                       │
                検索入力
                       │
                       ▼
              ┌─────────────────┐
              │ フィルタリング  │
              │ toLowerCase     │
              │ includes        │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ 項目選択        │
              │ onSelect        │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ handleNavigate  │
              │ - setOpen(false)│
              │ - navigate(path)│
              └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CommandBar.tsx | `packages/desktop-client/src/components/CommandBar.tsx` | ソース | メインコンポーネント |
| useAccounts.ts | `packages/desktop-client/src/hooks/useAccounts.ts` | ソース | 口座取得Hook |
| useReports.ts | `packages/desktop-client/src/hooks/useReports.ts` | ソース | レポート取得Hook |
| useModalState.ts | `packages/desktop-client/src/hooks/useModalState.ts` | ソース | モーダル状態Hook |
| useNavigate.ts | `packages/desktop-client/src/hooks/useNavigate.ts` | ソース | ナビゲーションHook |
| CellValue.tsx | `packages/desktop-client/src/components/spreadsheet/CellValue.tsx` | ソース | スプレッドシートセル値表示 |
| bindings.ts | `packages/desktop-client/src/spreadsheet/bindings.ts` | ソース | 残高バインディング定義 |
