# 画面設計書 22-アカウント情報画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおけるアカウント情報画面の設計仕様を記述したものです。ユーザープロフィール情報の表示・編集機能を提供し、名前、メール、パスワード、ニュースレター購読状態などの管理を可能にします。

### 本画面の処理概要

本画面は、ログイン済みユーザーの個人情報を表示・編集するためのプロフィール管理画面です。ユーザーは自身のアカウント情報を確認し、必要に応じて更新することができます。

**業務上の目的・背景**：eコマースアプリにおいて、ユーザーが自身の個人情報を管理できることは重要な機能です。配送先情報や連絡先の正確性を維持することで、スムーズな購入・配送プロセスを実現します。また、パスワード変更機能により、セキュリティを維持することができます。本画面はGDPR等のプライバシー規制にも対応し、アカウント削除機能も提供しています。

**画面へのアクセス方法**：ダッシュボード画面のアカウントセクション、またはナビゲーションメニューから「アカウント情報」をタップしてアクセスします。

**主要な操作・処理内容**：
1. 画面初期化時にアカウント情報をAPIから取得して表示する
2. 名前（姓・名）、メールアドレス、電話番号を編集する
3. 生年月日、性別を設定する
4. プロフィール画像を変更・削除する
5. パスワードを変更する（現在のパスワード、新しいパスワード、確認用パスワード）
6. ニュースレター購読の有効/無効を切り替える
7. 保存ボタンでアカウント情報を更新する
8. アカウントを削除する

**画面遷移**：ダッシュボード画面から本画面に遷移します。保存完了後は前の画面に戻ります。アカウント削除後はホーム画面に遷移します。

**権限による表示制御**：ログイン済みユーザーのみアクセス可能です。アカウント削除時はパスワードによる再認証が必要です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 48 | アカウント情報表示 | 主機能 | ユーザープロフィール情報の表示 |
| 49 | アカウント情報更新 | 補助機能 | ユーザープロフィール情報の編集・更新処理 |
| 50 | アカウント削除 | 補助機能 | ユーザーアカウントの削除処理 |

## 画面種別

編集

## URL/ルーティング

ルート名: `accountInfo`（routes定義による）

## 入出力項目

### 入力項目

| 項目名 | 入出力 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|------|------|---------------|------|
| firstName | 入力 | String | 必須 | 空白チェック | 名 |
| lastName | 入力 | String | 必須 | 空白チェック | 姓 |
| email | 入力 | String | 必須 | メール形式チェック | メールアドレス |
| phone | 入力 | String | 任意 | 電話番号形式チェック | 電話番号 |
| dateOfBirth | 入力 | String | 任意 | 日付形式 | 生年月日 |
| gender | 入力 | String | 任意 | 選択肢から選択 | 性別 |
| currentPassword | 入力 | String | 条件付き | パスワード変更時必須 | 現在のパスワード |
| newPassword | 入力 | String | 条件付き | パスワード変更時必須 | 新しいパスワード |
| confirmNewPassword | 入力 | String | 条件付き | newPasswordと一致 | 確認用パスワード |
| avatar | 入力 | XFile | 任意 | 画像ファイル | プロフィール画像 |
| subscribeNewsletter | 入力 | bool | 任意 | - | ニュースレター購読 |
| deleteAccountPassword | 入力 | String | 条件付き | 削除時必須 | 削除確認用パスワード |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| プロフィール画像 | Image | ユーザーのアバター画像 |
| 名 | String | ユーザーの名 |
| 姓 | String | ユーザーの姓 |
| メールアドレス | String | ユーザーのメールアドレス |
| 電話番号 | String | ユーザーの電話番号 |
| 生年月日 | String | ユーザーの生年月日 |
| 性別 | String | ユーザーの性別 |
| ニュースレター購読状態 | bool | 購読中/未購読のトグル状態 |

## イベント仕様

### 1-画面初期化イベント

画面初期化時（initState）にAccountInfoBlocを通じてAccountInfoDetailsEventが発行され、アカウント情報の取得が開始されます。

処理フロー：
1. パスワード関連のコントローラを初期化（空文字設定）
2. context.read<AccountInfoBloc>()でBlocインスタンスを取得
3. AccountInfoDetailsEventを発行
4. AccountInfoRepository.callAccountDetailsApiが呼び出される
5. 成功時はAccountInfoDetailStateが発行され、各コントローラにデータが設定される

### 2-保存ボタン押下イベント

保存ボタン押下時に_onPressSaveButtonが呼び出され、フォームバリデーション後にアカウント情報更新処理が実行されます。

処理フロー：
1. _formKey.currentState.validate()でフォームバリデーション
2. バリデーション成功時、処理中ダイアログを表示
3. AccountInfoUpdateEventを発行（全フィールドを引数として渡す）
4. 成功時：成功メッセージ表示、SharedPreferences更新、前画面に戻る
5. 失敗時：エラーメッセージを表示

### 3-アカウント削除イベント

アカウント削除ボタン押下時にAccountInfoDeleteEventが発行され、パスワード確認後にアカウント削除処理が実行されます。

処理フロー：
1. パスワード入力ダイアログを表示
2. AccountInfoDeleteEventを発行
3. 成功時：ログアウト処理実行、SharedPreferencesクリア、ホーム画面へ遷移
4. 失敗時：エラーメッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | customers | SELECT | ログイン中ユーザーの情報を取得 |
| 保存ボタン押下 | customers | UPDATE | ユーザー情報を更新 |
| アカウント削除 | customers | DELETE | ユーザーアカウントを削除 |

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

#### customers

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | first_name, last_name, email, phone, date_of_birth, gender | ログインユーザーID | 初期表示用 |
| UPDATE | first_name | フォーム入力値 | 名 |
| UPDATE | last_name | フォーム入力値 | 姓 |
| UPDATE | email | フォーム入力値 | メールアドレス |
| UPDATE | phone | フォーム入力値 | 電話番号 |
| UPDATE | date_of_birth | フォーム入力値 | 生年月日 |
| UPDATE | gender | フォーム入力値 | 性別 |
| UPDATE | password | フォーム入力値（ハッシュ化） | 新しいパスワード |
| UPDATE | subscribed_to_newsletter | フォーム入力値 | ニュースレター購読 |
| DELETE | * | ログインユーザーID | アカウント削除 |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示内容 | 表示条件 |
|--------------|--------------|---------|---------|
| タイトル | StringConstants.accountInfo | アカウント情報 | AppBarタイトル |
| ボタン | StringConstants.save | 保存 | 保存ボタンラベル |
| 成功 | accountUpdate.message | 更新成功メッセージ | 更新成功時 |
| エラー | StringConstants.invalidData | 無効なデータです | バリデーションエラー時 |
| 処理中 | StringConstants.processWaitingMsg | 処理中... | 保存処理中ダイアログ |
| 成功 | baseModel.message | 削除成功メッセージ | アカウント削除成功時 |

## 例外処理

| 例外状況 | 処理内容 | ユーザーへの表示 |
|---------|---------|----------------|
| API通信エラー | AccountInfoDetailState.failが発行される | AccountLoaderViewを表示 |
| 更新失敗 | AccountInfoUpdateState.failが発行される | エラーメッセージを表示 |
| 削除失敗 | AccountInfoDeleteState.failが発行される | エラーメッセージを表示 |
| バリデーションエラー | フォームが送信されない | 各フィールドにエラー表示 |
| パスワード不一致 | 更新処理が拒否される | エラーメッセージを表示 |

## 備考

- EmailValidator、PhoneNumberValidatorのmixinを使用してバリデーションを実装
- プロフィール画像は端末のカメラまたはギャラリーから選択可能
- 画像削除時はavatarパラメータに'delete'文字列を送信
- SharedPreferencesにユーザー名、メール、画像URLを保存し、アプリ全体で利用
- アカウント削除後はappStoragePref.onUserLogout()でログアウト処理を実行
- 性別の選択肢はgenderValuesリストで管理

---

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

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

### 推奨読解順序

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

まず、アカウント情報のデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account_info_model.dart | `lib/data_model/account_models/account_info_model.dart` | AccountInfoModelの構造を理解 |
| 1-2 | account_update_model.dart | `lib/data_model/account_models/account_update_model.dart` | AccountUpdateの構造を理解 |

**読解のコツ**: AccountInfoModelは取得用、AccountUpdateは更新応答用と役割が分かれています。

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

処理の起点となるファイル・関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | account_screen.dart | `lib/screens/account/view/account_screen.dart` | AccountScreenクラスがエントリーポイント |

**主要処理フロー**:
1. **21-41行目**: グローバル変数としてコントローラ、状態フラグを定義
2. **49-57行目**: initStateでBlocイベント発行、コントローラ初期化
3. **60-93行目**: buildメソッドでScaffold、AppBar、保存ボタンを構築
4. **96-151行目**: BlocConsumerで各状態に応じた処理を実行
5. **225-277行目**: _onPressSaveButtonで保存処理を実行

#### Step 3: ウィジェット層を理解する

画面を構成するサブウィジェットを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | profile_detail.dart | `lib/screens/account/widget/profile_detail.dart` | ProfileDetailViewウィジェットの構造 |
| 3-2 | profile_image_view.dart | `lib/screens/account/widget/profile_image_view.dart` | プロフィール画像表示・編集 |
| 3-3 | change_email_pass_view.dart | `lib/screens/account/widget/change_email_pass_view.dart` | パスワード変更フォーム |
| 3-4 | account_loader_view.dart | `lib/screens/account/widget/account_loader_view.dart` | ローディング表示 |

#### Step 4: Bloc層を理解する

状態管理と非同期処理の流れを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | account_info_bloc.dart | `lib/screens/account/bloc/account_info_bloc.dart` | イベント処理とステート発行 |
| 4-2 | account_info_event.dart | `lib/screens/account/bloc/account_info_event.dart` | 各イベントの定義と引数 |
| 4-3 | account_info_state.dart | `lib/screens/account/bloc/account_info_state.dart` | 各ステートの定義 |
| 4-4 | account_info_repository.dart | `lib/screens/account/bloc/account_info_repository.dart` | API呼び出しの実装 |

**主要処理フロー**:
- **23-29行目** (account_info_bloc.dart): AccountInfoDetailsEventの処理
- **30-37行目**: AccountInfoUpdateEventの処理
- **38-50行目**: AccountInfoDeleteEventの処理

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

```
AccountScreen (account_screen.dart)
    │
    ├─ initState()
    │      └─ AccountInfoBloc.add(AccountInfoDetailsEvent)
    │
    ├─ build()
    │      ├─ AppBar (タイトル表示)
    │      ├─ _profileBloc() → BlocConsumer
    │      │      └─ ProfileDetailView (profile_detail.dart)
    │      │             ├─ ProfileImageView
    │      │             ├─ TextFormFields (名前、メール等)
    │      │             └─ ChangeEmailPassView
    │      └─ MaterialButton (保存ボタン)
    │             └─ _onPressSaveButton()
    │
    ├─ _onPressSaveButton()
    │      └─ AccountInfoBloc.add(AccountInfoUpdateEvent)
    │
    └─ AccountInfoBloc (account_info_bloc.dart)
           │
           ├─ AccountInfoDetailsEvent
           │      └─ AccountInfoRepository.callAccountDetailsApi()
           │
           ├─ AccountInfoUpdateEvent
           │      └─ AccountInfoRepository.callAccountUpdateApi()
           │
           └─ AccountInfoDeleteEvent
                  └─ AccountInfoRepository.callDeleteAccountApi()
                         └─ HomePageRepositoryImp.callLogoutApi()
```

### データフロー図

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

ログインユーザーID       ───▶ AccountInfoDetailsEvent          ───▶ 画面表示
                                    │
                                    ▼
                         AccountInfoRepository
                         .callAccountDetailsApi()
                                    │
                                    ▼
                         AccountInfoModel                     ───▶ フォームにデータ設定

フォーム入力データ       ───▶ AccountInfoUpdateEvent           ───▶ 更新結果
 ├─ firstName                       │
 ├─ lastName                        ▼
 ├─ email                  AccountInfoRepository
 ├─ phone                  .callAccountUpdateApi()
 ├─ dob                             │
 ├─ gender                          ▼
 ├─ password               AccountUpdate                      ───▶ SharedPreferences更新
 ├─ avatar                                                          │
 └─ newsletter                                                      ▼
                                                               前画面に戻る

deletePassword           ───▶ AccountInfoDeleteEvent          ───▶ ログアウト
                                    │                               │
                                    ▼                               ▼
                         AccountInfoRepository               ホーム画面へ遷移
                         .callDeleteAccountApi()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| account_screen.dart | `lib/screens/account/view/account_screen.dart` | ソース | 画面本体のStatefulWidget |
| profile_detail.dart | `lib/screens/account/widget/profile_detail.dart` | ソース | プロフィール詳細フォーム |
| profile_image_view.dart | `lib/screens/account/widget/profile_image_view.dart` | ソース | プロフィール画像表示・編集 |
| change_email_pass_view.dart | `lib/screens/account/widget/change_email_pass_view.dart` | ソース | パスワード変更フォーム |
| account_loader_view.dart | `lib/screens/account/widget/account_loader_view.dart` | ソース | ローディング表示 |
| account_info_bloc.dart | `lib/screens/account/bloc/account_info_bloc.dart` | ソース | 状態管理Bloc |
| account_info_event.dart | `lib/screens/account/bloc/account_info_event.dart` | ソース | Blocイベント定義 |
| account_info_state.dart | `lib/screens/account/bloc/account_info_state.dart` | ソース | Blocステート定義 |
| account_info_repository.dart | `lib/screens/account/bloc/account_info_repository.dart` | ソース | API通信リポジトリ |
| index.dart | `lib/screens/account/utils/index.dart` | ソース | 共通インポートファイル |
