# 機能設計書 72-ナビゲーションドロワー

## 概要

本ドキュメントは、ECモバイルアプリケーションにおけるサイドメニュー（ナビゲーションドロワー）機能の設計を記述する。

### 本機能の処理概要

本機能はアプリ内の各画面へのナビゲーションを提供するサイドメニューを実装する。商品カテゴリ一覧、ユーザーアカウント関連機能、CMSページ、設定（言語・通貨切替）へのアクセスを1箇所に集約し、ユーザーがアプリ内を効率的に移動できるようにする。

**業務上の目的・背景**：ECアプリでは多数の機能や画面が存在するため、ユーザーが目的の機能に素早くアクセスできるナビゲーション構造が重要である。ドロワーメニューを採用することで、画面スペースを有効活用しながら、主要機能への導線を常に提供できる。

**機能の利用シーン**：
- ホーム画面からカテゴリを選択して商品一覧を閲覧
- ログイン状態の確認とサインイン/サインアップへの遷移
- アカウント情報、注文履歴、ウィッシュリストへのアクセス
- 言語・通貨設定の変更
- CMSページ（利用規約、プライバシーポリシー等）の閲覧
- ログアウト処理

**主要な処理内容**：
1. ユーザーログイン状態の判定と表示切替
2. カテゴリ一覧の動的生成と階層ナビゲーション
3. ログインユーザー向けメニュー項目の表示/非表示制御
4. CMSページへのリンク表示
5. 言語・通貨選択画面への遷移
6. ログアウト処理の実行

**関連システム・外部連携**：
- Bagisto GraphQL API（カテゴリ一覧取得、通貨・言語一覧取得）
- SharedPreferences（ログイン状態、ユーザー情報保存）

**権限による制御**：ログイン状態によりメニュー項目の表示が変化する。未ログイン時は「サインアップまたはログイン」リンクが表示され、ログイン時はアカウント関連メニュー（ダッシュボード、注文履歴、ウィッシュリスト等）とログアウトボタンが表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ホーム画面 | 主画面 | ドロワーを開いてナビゲーション操作 |
| 4 | サインイン画面 | 遷移先画面 | 未ログイン時のサインインリンク |
| 22 | アカウント情報画面 | 遷移先画面 | ログイン時のアカウント情報リンク |
| 9 | サブカテゴリ画面 | 遷移先画面 | カテゴリ選択時のサブカテゴリ表示 |
| 8 | カテゴリ商品一覧画面 | 遷移先画面 | カテゴリダブルタップ時の商品一覧表示 |

## 機能種別

ナビゲーション / UI制御 / データ表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| isLoggedIn | bool | Yes | ユーザーログイン状態 | - |
| customerUserName | String? | No | ログインユーザー名 | - |
| image | String? | No | ユーザーアバター画像URL | - |
| customerLanguage | String? | No | 選択中の言語 | - |
| currencyLanguageList | CurrencyLanguageList? | No | 通貨・言語マスタデータ | - |
| customerCurrency | String? | No | 選択中の通貨 | - |
| customerDetails | AccountInfoModel? | No | ユーザーアカウント詳細情報 | - |
| loginCallback | Function? | No | ログイン状態変更時のコールバック | - |

### 入力データソース

- SharedPreferences（ログイン状態、ユーザー名、画像URL）
- GlobalData.categoriesDrawerData（カテゴリ一覧）
- GlobalData.cmsData（CMSページ一覧）
- DrawerPageRepository（カテゴリ、通貨・言語一覧取得API）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| drawerList | List<Widget> | ドロワーに表示するウィジェット一覧 |

### 出力先

- 画面表示（Drawer Widget）
- Navigator（各画面への遷移）

## 処理フロー

### 処理シーケンス

```
1. DrawerListView初期化
   └─ ログイン状態、ユーザー情報をパラメータから取得
   └─ SharedPreferences監視リスナー登録（customerDetails変更検知）

2. ドロワーUI構築（build()）
   └─ ユーザー情報セクション生成
   └─ カテゴリ一覧セクション生成
   └─ ログイン時：アカウント関連メニュー生成
   └─ CMSページリンク生成
   └─ 設定セクション（言語・通貨）生成
   └─ ログイン時：ログアウトボタン生成

3. カテゴリアイテムタップ処理
   └─ サブカテゴリあり：サブカテゴリ画面へ遷移
   └─ サブカテゴリなし：商品一覧画面へ遷移
   └─ ダブルタップ：直接商品一覧画面へ遷移

4. ログアウト処理
   └─ 確認ダイアログ表示
   └─ API呼び出し
   └─ SharedPreferences初期化
   └─ UI状態更新
```

### フローチャート

```mermaid
flowchart TD
    A[DrawerListView初期化] --> B[ログイン状態判定]
    B --> C{isLoggedIn?}
    C -->|Yes| D[ログインユーザー情報表示]
    C -->|No| E[サインアップ/ログインリンク表示]
    D --> F[カテゴリ一覧表示]
    E --> F
    F --> G{isLoggedIn?}
    G -->|Yes| H[アカウントメニュー表示]
    G -->|No| I[CMSページ表示]
    H --> J[ダッシュボード]
    H --> K[ダウンロード可能商品]
    H --> L[住所管理]
    H --> M[レビュー]
    H --> N[ウィッシュリスト]
    H --> O[注文履歴]
    J --> I
    K --> I
    L --> I
    M --> I
    N --> I
    O --> I
    I --> P[設定セクション表示]
    P --> Q[言語選択]
    P --> R[通貨選択]
    Q --> S{isLoggedIn?}
    R --> S
    S -->|Yes| T[GDPR/ログアウト表示]
    S -->|No| U[ドロワー完成]
    T --> U
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-72-01 | ログイン依存表示 | アカウント関連メニューはログインユーザーのみ表示 | 常時 |
| BR-72-02 | カテゴリ階層ナビゲーション | サブカテゴリがある場合はサブカテゴリ画面、ない場合は商品一覧画面へ遷移 | カテゴリタップ時 |
| BR-72-03 | ダブルタップショートカット | カテゴリをダブルタップすると直接商品一覧画面へ遷移 | カテゴリダブルタップ時 |
| BR-72-04 | ログアウト確認 | ログアウト時は確認ダイアログを表示 | ログアウトボタンタップ時 |
| BR-72-05 | インターネット接続確認 | 画面遷移前にインターネット接続を確認し、未接続時はエラー通知 | メニュータップ時 |

### 計算ロジック

特になし。

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

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

本機能ではローカルデータベース操作は発生しない。SharedPreferencesによるキーバリューストアアクセスのみ。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ネットワークエラー | インターネット未接続 | 「インターネット接続の問題」通知表示、遷移中止 |
| - | API呼び出し失敗 | カテゴリ取得失敗 | エラーメッセージ表示 |
| - | ログアウト失敗 | ログアウトAPI失敗 | エラーメッセージ表示（ただしローカルはクリア） |

### リトライ仕様

カテゴリ取得API等のリトライはDrawerBlocで管理。特別なリトライロジックは実装されていない。

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

本機能ではトランザクション管理は不要（API呼び出しのみ）。

## パフォーマンス要件

- ドロワーオープン：即時（既にメモリ上にデータがある場合）
- カテゴリデータ取得：ホーム画面表示時に事前取得済み

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

- ログアウト時はSharedPreferencesからユーザー情報を完全にクリア
- ログイン状態の判定はSharedPreferencesのcustomerLoggedInフラグに依存

## 備考

- カテゴリデータはGlobalData.categoriesDrawerDataに格納され、アプリ起動時に取得される
- CMSデータはGlobalData.cmsDataに格納される
- RTL（右から左）言語対応：アラビア語の場合、矢印アイコンが反転

---

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

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

### 推奨読解順序

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

ドロワーで使用される主要なデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | drawer_state.dart | `lib/screens/drawer/bloc/drawer_state.dart` | DrawerPageBaseState、FetchDrawerPageDataStateの構造 |
| 1-2 | drawer_events.dart | `lib/screens/drawer/bloc/drawer_events.dart` | FetchDrawerPageEvent、CurrencyLanguageEventの定義 |

**読解のコツ**: FlutterのBLoCパターンでは、State（状態）とEvent（イベント）が分離されている。Stateはステータス（success/fail）とデータを保持し、Eventは状態変更のトリガーを表す。

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

DrawerListViewの初期化と全体構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | drawer_list_view.dart | `lib/screens/drawer/drawer_list_view.dart` | StatefulWidgetの構造、パラメータ定義 |

**主要処理フロー**:
1. **17-41行目**: DrawerListViewクラス定義とパラメータ
2. **45-57行目**: initState()でSharedPreferences監視リスナー登録
3. **60-345行目**: build()メソッドでドロワーUI構築

#### Step 3: ドロワーUI構築を理解する

build()メソッド内のUI構築ロジックを詳細に理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | drawer_list_view.dart | `lib/screens/drawer/drawer_list_view.dart` | drawerListへのウィジェット追加ロジック |

**主要処理フロー**:
- **65-156行目**: ユーザー情報セクション（ログイン状態による分岐）
- **157-171行目**: カテゴリセクション（GlobalData.categoriesDrawerDataから生成）
- **173-267行目**: ログインユーザー向けアカウントメニュー
- **269-285行目**: CMSページセクション
- **286-323行目**: 設定セクション（言語・通貨）
- **325-330行目**: ログアウトボタン（ログイン時のみ）

#### Step 4: カテゴリアイテムの動作を理解する

カテゴリ選択時のナビゲーション処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | drawer_category_item.dart | `lib/screens/drawer/widget/drawer_category_item.dart` | カテゴリタップ時の遷移ロジック |

**主要処理フロー**:
- **29-46行目**: onDoubleTap()で直接カテゴリ商品一覧画面へ遷移
- **62-77行目**: onTap()でサブカテゴリ有無による分岐遷移

#### Step 5: ログアウト処理を理解する

ログアウトボタンの動作と確認ダイアログを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | log_out_button.dart | `lib/screens/drawer/widget/log_out_button.dart` | ログアウト確認と実行処理 |

**主要処理フロー**:
- **60-96行目**: _onPressedLogout()で確認ダイアログ表示
- **99-138行目**: _onPressConfirmLogout()でAPI呼び出しとSharedPreferencesクリア

#### Step 6: APIリポジトリを理解する

カテゴリ・通貨言語データ取得のAPI呼び出しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | drawer_repository.dart | `lib/screens/drawer/bloc/drawer_repository.dart` | getDrawerCategoriesList()、getLanguageCurrencyList() |
| 6-2 | drawer_bloc.dart | `lib/screens/drawer/bloc/drawer_bloc.dart` | イベント処理とState遷移 |

**主要処理フロー**:
- **24-32行目（repository）**: getDrawerCategoriesList()でカテゴリ取得
- **35-44行目（repository）**: getLanguageCurrencyList()で通貨・言語取得
- **22-37行目（bloc）**: FetchDrawerPageEvent処理
- **38-49行目（bloc）**: CurrencyLanguageEvent処理

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

```
DrawerListView
    │
    ├─ initState()
    │      └─ appStoragePref.configurationStorage.listenKey()
    │
    ├─ build()
    │      │
    │      ├─ ユーザー情報セクション
    │      │      └─ Navigator.pushNamed(accountInfo / signIn)
    │      │
    │      ├─ カテゴリセクション
    │      │      └─ DrawerCategoryItem
    │      │             ├─ onDoubleTap → Navigator.pushNamed(categoryScreen)
    │      │             └─ onTap → Navigator.pushNamed(drawerSubCategoryScreen / categoryScreen)
    │      │
    │      ├─ アカウントメニュー（ログイン時）
    │      │      └─ DrawerAddItemList × 6
    │      │             └─ Navigator.pushNamed(各画面)
    │      │
    │      ├─ CMSセクション
    │      │      └─ CmsItemsList
    │      │
    │      ├─ 設定セクション
    │      │      └─ DrawerAddItemList × 2（言語・通貨）
    │      │
    │      └─ ログアウト（ログイン時）
    │             └─ LogoutButton
    │                    ├─ _onPressedLogout() → AlertDialog
    │                    └─ _onPressConfirmLogout()
    │                           ├─ HomePageRepositoryImp().callLogoutApi()
    │                           └─ appStoragePref.onUserLogout()
    │
    └─ _fetchSharedPreferenceData()
           └─ appStoragePref.getCustomerLoggedIn() / getCustomerName() / getCustomerImage()
```

### データフロー図

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

GlobalData.categoriesDrawerData ──▶ DrawerListView.build() ──▶ カテゴリリストUI
                                        │
SharedPreferences ─────────────────────▶│──▶ ユーザー情報UI
(isLoggedIn, customerName, image)       │
                                        │
GlobalData.cmsData ────────────────────▶│──▶ CMSリンクUI
                                        │
CurrencyLanguageList ──────────────────▶│──▶ 言語・通貨選択UI

ユーザータップ ──────▶ Navigator.pushNamed() ──▶ 各画面遷移

ログアウトタップ ──▶ HomePageRepositoryImp().callLogoutApi() ──▶ API応答
                        │
                        └─▶ appStoragePref.onUserLogout() ──▶ SharedPreferencesクリア
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| drawer_list_view.dart | `lib/screens/drawer/drawer_list_view.dart` | ソース | ドロワーメインビュー |
| drawer_category_item.dart | `lib/screens/drawer/widget/drawer_category_item.dart` | ソース | カテゴリ項目ウィジェット |
| drawer_add_item_view.dart | `lib/screens/drawer/widget/drawer_add_item_view.dart` | ソース | メニュー項目ウィジェット |
| log_out_button.dart | `lib/screens/drawer/widget/log_out_button.dart` | ソース | ログアウトボタン |
| drawer_bloc.dart | `lib/screens/drawer/bloc/drawer_bloc.dart` | ソース | ドロワーBLoC |
| drawer_repository.dart | `lib/screens/drawer/bloc/drawer_repository.dart` | ソース | APIリポジトリ |
| drawer_state.dart | `lib/screens/drawer/bloc/drawer_state.dart` | ソース | 状態定義 |
| drawer_events.dart | `lib/screens/drawer/bloc/drawer_events.dart` | ソース | イベント定義 |
| index.dart | `lib/screens/drawer/utils/index.dart` | ソース | エクスポート定義 |
