# 画面設計書 24-住所追加・編集画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおける住所追加・編集画面の設計仕様を記述したものです。新規住所の登録および既存住所の編集機能を提供し、配送先情報の管理を可能にします。

### 本画面の処理概要

本画面は、新規住所の追加または既存住所の編集を行うためのフォーム画面です。国・州の選択、住所詳細の入力、位置情報からの住所取得機能を提供します。

**業務上の目的・背景**：eコマースにおいて、正確な配送先住所の入力は注文処理の基盤となります。ユーザーが住所を正確かつ効率的に入力できるよう、国・州のドロップダウン選択、位置情報による自動入力、フォームバリデーションなどの機能を提供します。チェックアウト時の住所追加にも対応しています。

**画面へのアクセス方法**：住所一覧画面から「新しい住所を追加」ボタン押下、または既存住所の「編集」ボタン押下でアクセスします。チェックアウト画面からも新規住所追加として遷移可能です。

**主要な操作・処理内容**：
1. 画面初期化時に国・州データをAPIから取得する
2. 編集モードの場合、既存住所データをフォームに設定する
3. 名前、会社名、住所、国、州、市、郵便番号、電話番号を入力する
4. AppBarの位置アイコンから位置情報選択画面へ遷移し、住所を自動入力する
5. 保存ボタンで住所を登録・更新する
6. デフォルト住所として設定するオプションを選択する

**画面遷移**：住所一覧画面またはチェックアウト画面から本画面に遷移します。位置情報選択画面へ遷移し、住所データを受け取ることができます。保存成功後は前画面に戻ります。

**権限による表示制御**：ログイン済みユーザーのみアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | 住所追加 | 主機能 | 新規住所の登録処理 |
| 54 | 住所編集 | 主機能 | 既存住所の編集処理 |
| 57 | 国・州データ取得 | 補助機能 | 住所登録用の国・州リスト取得 |

## 画面種別

登録 / 編集

## URL/ルーティング

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

## 入出力項目

### 入力パラメータ

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| isEdit | 入力 | bool | 任意 | 編集モードかどうか |
| addressModel | 入力 | AddressData | 任意 | 編集対象の住所データ |
| isCheckout | 入力 | bool | 任意 | チェックアウトからのアクセスかどうか |

### フォーム入力項目

| 項目名 | 入出力 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|------|------|---------------|------|
| firstName | 入力 | String | 必須 | 空白チェック | 名 |
| lastName | 入力 | String | 必須 | 空白チェック | 姓 |
| email | 入力 | String | 必須 | メール形式 | メールアドレス |
| companyName | 入力 | String | 任意 | - | 会社名 |
| phone | 入力 | String | 必須 | 電話番号形式 | 電話番号 |
| street1 | 入力 | String | 必須 | 空白チェック | 住所 |
| country | 入力 | String | 必須 | 選択必須 | 国 |
| state | 入力 | String | 必須 | 選択または入力 | 都道府県/州 |
| city | 入力 | String | 必須 | 空白チェック | 市区町村 |
| zipCode | 入力 | String | 必須 | 空白チェック | 郵便番号 |
| vatId | 入力 | String | 任意 | - | VAT ID |
| isDefault | 入力 | bool | 任意 | - | デフォルト住所として設定 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| AppBarタイトル | String | 新規追加時「住所を追加」、編集時「住所を編集」 |
| 位置情報ボタン | Icon | AppBar右側の現在地取得ボタン |
| 国ドロップダウン | List<String> | 選択可能な国の一覧 |
| 州ドロップダウン/テキストフィールド | List<String> or TextField | 国に応じて州選択または自由入力 |

## イベント仕様

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

画面初期化時（initState）に既存データの設定と国・州データの取得が行われます。

処理フロー：
1. SharedPreferencesからユーザー名を取得し、名・姓フィールドに設定
2. 編集モードの場合、addressModelから各フィールドに値を設定
3. AddEditAddressBlocを取得
4. AddressCountryEventが発行され、国・州データを取得

### 2-国選択イベント

国ドロップダウンで国を選択した際の処理です。

処理フロー：
1. dropdownUpdateメソッドが呼び出される
2. 選択された国をcountryListから検索
3. selectedCountry、countryCodeを更新
4. 選択国に州データがある場合、selectedStateを州リストの先頭に設定
5. setStateでUIを更新

### 3-州選択イベント

州ドロップダウンで州を選択した際の処理です。

処理フロー：
1. dropdownUpdateメソッドが呼び出される
2. 選択された州をselectedCountry.statesから検索
3. selectedState、stateNameを更新
4. stateNameControllerに州コードを設定

### 4-位置情報取得イベント

AppBarの位置情報ボタン押下時の処理です。

処理フロー：
1. LocationScreenへNavigator.pushで遷移
2. 戻り値としてMap型の住所データを受け取る
3. street1, city, zip, state, countryをフォームに設定
4. selectedCountry、countryCodeを更新
5. setStateでUIを更新

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

保存ボタン押下時にSaveAddressButtonウィジェット内で処理が実行されます。

処理フロー：
1. フォームバリデーションを実行
2. 編集モード：FetchEditAddressEventを発行
3. 新規モード：FetchAddAddressEventを発行
4. 成功時：成功メッセージ表示、AddressDataを戻り値として前画面に戻る
5. 失敗時：エラーメッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 住所追加 | addresses | INSERT | 新規住所レコードを作成 |
| 住所編集 | addresses | UPDATE | 既存住所レコードを更新 |
| 国・州取得 | countries, states | SELECT | 国・州マスタデータを取得 |

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

#### addresses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | first_name | フォーム入力値 | 名 |
| INSERT/UPDATE | last_name | フォーム入力値 | 姓 |
| INSERT/UPDATE | email | フォーム入力値 | メールアドレス |
| INSERT/UPDATE | company_name | フォーム入力値 | 会社名 |
| INSERT/UPDATE | phone | フォーム入力値 | 電話番号 |
| INSERT/UPDATE | address1 | フォーム入力値 | 住所 |
| INSERT/UPDATE | country | 選択された国コード | 国コード |
| INSERT/UPDATE | state | 選択された州コード | 州コード |
| INSERT/UPDATE | city | フォーム入力値 | 市区町村 |
| INSERT/UPDATE | postcode | フォーム入力値 | 郵便番号 |
| INSERT/UPDATE | vat_id | フォーム入力値 | VAT ID |
| INSERT/UPDATE | default_address | チェックボックス値 | デフォルトフラグ |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示内容 | 表示条件 |
|--------------|--------------|---------|---------|
| タイトル | StringConstants.addAddressLabel | 住所を追加 | 新規追加時 |
| タイトル | StringConstants.editAddressLabel | 住所を編集 | 編集時 |
| ラベル | StringConstants.countryLabel | 国 | 国フィールドラベル |
| ラベル | StringConstants.stateLabel | 都道府県/州 | 州フィールドラベル |
| ラベル | StringConstants.cityLabel | 市区町村 | 市区町村フィールドラベル |
| プレースホルダー | StringConstants.countryHint | 国を選択 | 国ドロップダウン |
| プレースホルダー | StringConstants.stateHint | 都道府県/州を選択 | 州ドロップダウン |
| プレースホルダー | StringConstants.cityHint | 市区町村を入力 | 市区町村フィールド |
| エラー | StringConstants.pleaseFillLabel + フィールド名 | 入力必須エラー | バリデーションエラー時 |
| 成功 | updateAddressModel.message | 更新成功 | 編集成功時 |
| 成功 | baseModel.message | 追加成功 | 新規追加成功時 |

## 例外処理

| 例外状況 | 処理内容 | ユーザーへの表示 |
|---------|---------|----------------|
| 国・州データ取得失敗 | AddressCountryState.failが発行される | EmptyDataViewを表示 |
| 住所追加失敗 | FetchAddAddressState.failが発行される | エラーメッセージを表示 |
| 住所編集失敗 | FetchEditAddressState.failが発行される | エラーメッセージを表示 |
| バリデーションエラー | フォームが送信されない | 各フィールドにエラー表示 |
| 位置情報取得失敗 | LocationScreenでエラー処理 | 前画面に戻る |

## 備考

- 国に州データがある場合はドロップダウン選択、ない場合はテキストフィールドで入力
- 編集モード時はisEdit引数とaddressModelが渡される
- 位置情報選択画面から住所データを取得可能（street1, street2, street3, city, state, zip, country, countryCode）
- GetAddressFormウィジェットで名前、メール、電話番号、住所、郵便番号フィールドを表示
- CommonDropDownFieldウィジェットで国・州選択を表示
- SaveAddressButtonウィジェットで保存処理を実行
- SharedPreferencesからメールアドレスを取得してデフォルト設定

---

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

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

### 推奨読解順序

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

まず、住所情報と国・州データの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address_model.dart | `lib/screens/address_list/data_model/address_model.dart` | AddressDataの全フィールドを確認 |
| 1-2 | country_model.dart | `lib/screens/address_list/data_model/country_model.dart` | CountriesData、Data、States構造を理解 |
| 1-3 | update_address_model.dart | `lib/screens/address_list/data_model/update_address_model.dart` | UpdateAddressModelの構造を確認 |

**読解のコツ**: CountriesDataのData（国）がList<States>を持ち、国に州が紐づく親子関係になっています。

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

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

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

**主要処理フロー**:
1. **61-102行目**: initStateで既存データ設定、ユーザー名取得
2. **116-170行目**: buildメソッドでScaffold、AppBar（位置情報ボタン含む）を構築
3. **173-277行目**: BlocConsumerで状態に応じた処理
4. **327-434行目**: buildUIでフォーム表示、国・州ドロップダウン構築
5. **453-474行目**: dropdownUpdateで国・州選択時の処理

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | get_address_form.dart | `lib/screens/add_edit_address/view/widget/get_address_form.dart` | 住所入力フォーム |
| 3-2 | save_address_button.dart | `lib/screens/add_edit_address/view/widget/save_address_button.dart` | 保存ボタンと保存処理 |
| 3-3 | add_edit_address_loader_view.dart | `lib/screens/add_edit_address/view/widget/add_edit_address_loader_view.dart` | ローディング表示 |

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | add_edit_address_bloc.dart | `lib/screens/add_edit_address/bloc/add_edit_address_bloc.dart` | イベント処理とステート発行 |
| 4-2 | add_edit_address_event.dart | `lib/screens/add_edit_address/bloc/add_edit_address_event.dart` | 各イベントの定義 |
| 4-3 | add_edit_address_state.dart | `lib/screens/add_edit_address/bloc/add_edit_address_state.dart` | 各ステートの定義 |

**主要処理フロー**:
- **29-64行目** (add_edit_address_bloc.dart): FetchEditAddressEventの処理
- **65-88行目**: FetchAddAddressEventの処理
- **88-96行目**: AddressCountryEventの処理

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

```
AddNewAddress (add_edit_address_screen.dart)
    │
    ├─ initState()
    │      └─ _fetchSharedPreferenceData()
    │
    ├─ build()
    │      ├─ AppBar
    │      │      └─ 位置情報ボタン → LocationScreen
    │      │             └─ 戻り値でフォーム更新
    │      │
    │      └─ _addEditAddressBloc() → BlocConsumer
    │             └─ buildUI()
    │                    ├─ GetAddressForm
    │                    ├─ CommonDropDownField (国)
    │                    │      └─ dropdownUpdate()
    │                    ├─ CommonDropDownField (州) / TextField
    │                    │      └─ dropdownUpdate()
    │                    ├─ TextField (市区町村)
    │                    └─ SaveAddressButton
    │                           └─ 保存処理
    │
    └─ AddEditAddressBloc (add_edit_address_bloc.dart)
           │
           ├─ AddressCountryEvent
           │      └─ AddEditAddressRepository.callCountriesData()
           │
           ├─ FetchAddAddressEvent
           │      └─ AddEditAddressRepository.callCreateAddress()
           │
           └─ FetchEditAddressEvent
                  └─ AddEditAddressRepository.callEditAddressApi()
```

### データフロー図

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

isEdit, addressModel     ───▶ initState()                     ───▶ フォーム初期値設定
                                    │
                                    ▼
                         AddressCountryEvent
                                    │
                                    ▼
                         AddEditAddressRepository
                         .callCountriesData()
                                    │
                                    ▼
                         CountriesData                        ───▶ 国ドロップダウン表示
                          └─ Data[] (国)                           │
                              └─ States[] (州)                     ▼
                                                               州ドロップダウン表示

LocationScreen戻り値     ───▶ フォーム更新                     ───▶ 住所フィールド自動入力
 ├─ street1/2/3                     │
 ├─ city                            ▼
 ├─ state               国・州選択状態を更新
 ├─ zip
 ├─ country
 └─ countryCode

フォーム入力データ       ───▶ FetchAddAddressEvent            ───▶ 新規住所登録
                         または FetchEditAddressEvent              │
                                    │                              ▼
                                    ▼                         AddressData
                         AddEditAddressRepository              戻り値として返却
                         .callCreateAddress()                      │
                         .callEditAddressApi()                     ▼
                                    │                         前画面に戻る
                                    ▼
                         BaseModel / UpdateAddressModel
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| add_edit_address_screen.dart | `lib/screens/add_edit_address/view/add_edit_address_screen.dart` | ソース | 画面本体のStatefulWidget |
| get_address_form.dart | `lib/screens/add_edit_address/view/widget/get_address_form.dart` | ソース | 住所入力フォーム |
| save_address_button.dart | `lib/screens/add_edit_address/view/widget/save_address_button.dart` | ソース | 保存ボタン |
| add_edit_address_loader_view.dart | `lib/screens/add_edit_address/view/widget/add_edit_address_loader_view.dart` | ソース | ローディング表示 |
| add_edit_address_bloc.dart | `lib/screens/add_edit_address/bloc/add_edit_address_bloc.dart` | ソース | 状態管理Bloc |
| add_edit_address_event.dart | `lib/screens/add_edit_address/bloc/add_edit_address_event.dart` | ソース | Blocイベント定義 |
| add_edit_address_state.dart | `lib/screens/add_edit_address/bloc/add_edit_address_state.dart` | ソース | Blocステート定義 |
| add_edit_address_repository.dart | `lib/screens/add_edit_address/bloc/add_edit_address_repository.dart` | ソース | API通信リポジトリ |
| location_screen.dart | `lib/screens/location/view/location_screen.dart` | ソース | 位置情報選択画面 |
| country_model.dart | `lib/screens/address_list/data_model/country_model.dart` | ソース | 国・州データモデル |
| index.dart | `lib/screens/add_edit_address/utils/index.dart` | ソース | 共通インポートファイル |
