# 画面設計書 23-住所一覧画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおける住所一覧画面の設計仕様を記述したものです。ユーザーが登録した配送先住所を一覧表示し、住所の追加、編集、削除、デフォルト設定の機能を提供します。

### 本画面の処理概要

本画面は、ログイン済みユーザーの登録済み住所を一覧形式で表示し、住所の管理機能を提供する画面です。チェックアウト時の配送先選択や、アカウント管理からのアクセスに対応しています。

**業務上の目的・背景**：eコマースにおいて、正確な配送先住所の管理は注文処理の根幹を成す重要な機能です。ユーザーは複数の住所（自宅、職場、実家等）を登録・管理し、注文時に適切な配送先を選択できる必要があります。デフォルト住所の設定機能により、毎回の住所選択の手間を省くことができます。

**画面へのアクセス方法**：アカウント情報画面から「住所管理」をタップ、またはチェックアウト画面から配送先住所選択時に本画面にアクセスします。ダッシュボードからも直接アクセス可能です。

**主要な操作・処理内容**：
1. 画面初期化時に登録済み住所一覧をAPIから取得して表示する
2. 「新しい住所を追加」ボタンで住所追加画面へ遷移する
3. 各住所カードの編集ボタンで住所編集画面へ遷移する
4. 各住所カードの削除ボタンで住所を削除する
5. 各住所をデフォルト住所に設定する
6. プルダウンリフレッシュで住所一覧を再取得する

**画面遷移**：アカウント情報画面またはチェックアウト画面から本画面に遷移します。新規追加・編集ボタン押下時は住所追加・編集画面へ遷移します。

**権限による表示制御**：ログイン済みユーザーのみアクセス可能です。ダッシュボードからのアクセス時は最大5件の住所を表示し、AppBarは非表示になります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 52 | 住所一覧表示 | 主機能 | 登録済み住所の一覧表示 |
| 55 | 住所削除 | 補助機能 | 登録済み住所の削除処理 |
| 56 | デフォルト住所設定 | 補助機能 | 住所をデフォルトに設定する処理 |
| 53 | 住所追加 | 遷移先機能 | 住所追加画面への遷移 |
| 54 | 住所編集 | 遷移先機能 | 住所編集画面への遷移 |

## 画面種別

一覧

## URL/ルーティング

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

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| isFromDashboard | 入力 | bool | 任意 | ダッシュボードからのアクセスかどうか |

## 表示項目

### 住所カード

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 名前 | String | firstName + lastName |
| 会社名 | String | companyName（ある場合） |
| 住所 | String | address1 |
| 市区町村 | String | city |
| 都道府県/州 | String | stateName または state |
| 郵便番号 | String | postcode |
| 国名 | String | countryName |
| 電話番号 | String | phone |
| デフォルトフラグ | bool | isDefault（デフォルト住所かどうか） |
| VAT ID | String | vatId（ある場合） |

## イベント仕様

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

画面初期化時（initState）にAddressBlocを通じてFetchAddressEventが発行され、住所一覧の取得が開始されます。

処理フロー：
1. context.read<AddressBloc>()でBlocインスタンスを取得
2. FetchAddressEventを発行
3. AddressRepository.callAddressApiが呼び出される
4. 成功時はFetchAddressStateが発行され、_addressListメソッドで表示

### 2-住所削除イベント

住所カードの削除ボタン押下時にRemoveAddressEventが発行され、住所削除処理が実行されます。

処理フロー：
1. 削除確認ダイアログを表示
2. 確認後、RemoveAddressEvent(id)を発行
3. AddressRepository.callRemoveAddressApiが呼び出される
4. 成功時：成功メッセージ表示、一覧から該当住所を削除
5. 失敗時：エラーメッセージを表示

### 3-デフォルト住所設定イベント

住所カードのデフォルト設定ボタン押下時にSetDefaultAddressEventが発行されます。

処理フロー：
1. ShowLoaderStateでローダー表示
2. SetDefaultAddressEvent(id)を発行
3. AddressRepository.setDefaultAddressが呼び出される
4. 成功時：成功メッセージ表示、FetchAddressEventで一覧を再取得
5. 失敗時：エラーメッセージを表示

### 4-住所追加・編集への遷移イベント

追加ボタンまたは編集ボタン押下時に住所追加・編集画面へ遷移します。

処理フロー：
1. Navigator.pushNamedで住所追加・編集画面へ遷移
2. AddressNavigationDataを引数として渡す（isEdit, addressModel, isCheckout）
3. 遷移先から戻った際にfetchAddressData()で一覧を再取得

### 5-プルダウンリフレッシュイベント

画面を下に引っ張ることで住所一覧を再取得します。

処理フロー：
1. RefreshIndicatorで検出
2. 1秒後にFetchAddressEventを発行
3. 最新の住所一覧を取得・表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | addresses | SELECT | ログイン中ユーザーの住所一覧を取得 |
| 住所削除 | addresses | DELETE | 指定された住所を削除 |
| デフォルト設定 | addresses | UPDATE | 指定住所をデフォルトに設定 |

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

#### addresses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | customer_id = ログインユーザーID | 全住所情報を取得 |
| DELETE | * | id = 削除対象住所ID | 住所レコードを削除 |
| UPDATE | default_address | true | デフォルト住所フラグを更新 |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示内容 | 表示条件 |
|--------------|--------------|---------|---------|
| タイトル | StringConstants.address | 住所 | AppBarタイトル |
| ボタン | StringConstants.addNewAddress | 新しい住所を追加 | 追加ボタンラベル |
| 成功 | response.message | 削除成功メッセージ | 削除成功時 |
| 成功 | addressModel.message | 設定成功メッセージ | デフォルト設定成功時 |
| エラー | StringConstants.somethingWrong | エラーが発生しました | 処理失敗時 |

## 例外処理

| 例外状況 | 処理内容 | ユーザーへの表示 |
|---------|---------|----------------|
| 住所データなし | EmptyDataViewを表示 | 空の住所アイコンとメッセージを表示 |
| 住所リストが空 | AddNewAddressButtonを表示 | 住所追加ボタンのみを表示 |
| API通信エラー | FetchAddressState.failが発行される | EmptyDataViewを表示 |
| 削除失敗 | RemoveAddressState.failが発行される | エラーメッセージを表示 |
| デフォルト設定失敗 | SetDefaultAddressState.failが発行される | エラーメッセージを表示 |

## 備考

- isFromDashboardがtrueの場合、最大5件の住所を表示し、AppBarは非表示
- 住所データの有無はappStoragePref.setAddressData()でSharedPreferencesに保存
- SavedAddressListウィジェットで各住所カードを表示
- AddressLoaderウィジェットでローディング状態を表示
- RefreshIndicatorでプルダウンリフレッシュに対応

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address_model.dart | `lib/screens/address_list/data_model/address_model.dart` | AddressModel、AddressDataの構造を理解 |
| 1-2 | country_model.dart | `lib/screens/address_list/data_model/country_model.dart` | CountriesData、States構造を確認 |
| 1-3 | default_address_model.dart | `lib/screens/address_list/data_model/default_address_model.dart` | SetDefaultAddressモデルを確認 |

**読解のコツ**: AddressModelがList<AddressData>を持ち、各AddressDataが個別の住所を表します。JsonSerializableアノテーションに注目してください。

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

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

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

**主要処理フロー**:
1. **31-35行目**: initStateでAddressBlocを取得、FetchAddressEventを発行
2. **38-51行目**: buildメソッドでScaffold構築、isFromDashboardでAppBar表示を制御
3. **54-85行目**: BlocConsumerで各状態に応じた処理を実行
4. **88-119行目**: buildUIで状態に応じたウィジェットを返却
5. **122-228行目**: _addressListで住所一覧を構築

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | saved_address_list.dart | `lib/screens/address_list/view/widget/saved_address_list.dart` | 住所カードウィジェット |
| 3-2 | add_new_address_button.dart | `lib/screens/address_list/view/widget/add_new_address_button.dart` | 新規追加ボタン |
| 3-3 | address_loader_view.dart | `lib/screens/address_list/view/widget/address_loader_view.dart` | ローディング表示 |

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | イベント処理とステート発行 |
| 4-2 | address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | 各イベントの定義 |
| 4-3 | address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | 各ステートの定義 |
| 4-4 | address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | API呼び出しの実装 |

**主要処理フロー**:
- **24-30行目** (address_bloc.dart): FetchAddressEventの処理
- **31-39行目**: RemoveAddressEventの処理
- **40-55行目**: SetDefaultAddressEventの処理

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

```
AddressScreen (address_screen.dart)
    │
    ├─ initState()
    │      └─ AddressBloc.add(FetchAddressEvent)
    │
    ├─ build()
    │      ├─ AppBar (isFromDashboardで表示制御)
    │      └─ _addressBloc() → BlocConsumer
    │             ├─ AddressLoader (ローディング中)
    │             ├─ EmptyDataView (データなし)
    │             └─ _addressList() (データあり)
    │                    ├─ AddNewAddressButton
    │                    ├─ RefreshIndicator
    │                    └─ ListView.builder
    │                           └─ SavedAddressList (各住所カード)
    │
    ├─ 住所追加ボタン押下
    │      └─ Navigator.pushNamed(addAddressScreen)
    │             └─ fetchAddressData() (戻り時)
    │
    └─ AddressBloc (address_bloc.dart)
           │
           ├─ FetchAddressEvent
           │      └─ AddressRepository.callAddressApi()
           │
           ├─ RemoveAddressEvent
           │      └─ AddressRepository.callRemoveAddressApi()
           │
           └─ SetDefaultAddressEvent
                  └─ AddressRepository.setDefaultAddress()
                         └─ FetchAddressEvent (再取得)
```

### データフロー図

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

isFromDashboard      ───▶ AddressScreen.build()            ───▶ UI制御
(ダッシュボード判定)              │                               (AppBar表示、件数制限)
                                 ▼
ログインユーザーID       ───▶ FetchAddressEvent               ───▶ 住所一覧表示
                                 │
                                 ▼
                         AddressRepository
                         .callAddressApi()
                                 │
                                 ▼
                         AddressModel                        ───▶ ListView.builder
                          └─ AddressData[]                        │
                                                                  ▼
                                                            SavedAddressList

住所ID              ───▶ RemoveAddressEvent                ───▶ 一覧から削除
                                 │
                                 ▼
                         AddressRepository
                         .callRemoveAddressApi()
                                 │
                                 ▼
                         BaseModel (成功/失敗)              ───▶ メッセージ表示

住所ID              ───▶ SetDefaultAddressEvent            ───▶ 一覧再取得
                                 │
                                 ▼
                         AddressRepository
                         .setDefaultAddress()
                                 │
                                 ▼
                         SetDefaultAddress                  ───▶ FetchAddressEvent
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| address_screen.dart | `lib/screens/address_list/view/address_screen.dart` | ソース | 画面本体のStatefulWidget |
| saved_address_list.dart | `lib/screens/address_list/view/widget/saved_address_list.dart` | ソース | 住所カードウィジェット |
| add_new_address_button.dart | `lib/screens/address_list/view/widget/add_new_address_button.dart` | ソース | 新規追加ボタン |
| address_loader_view.dart | `lib/screens/address_list/view/widget/address_loader_view.dart` | ソース | ローディング表示 |
| address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | ソース | 状態管理Bloc |
| address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | ソース | Blocイベント定義 |
| address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | ソース | Blocステート定義 |
| address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | ソース | API通信リポジトリ |
| address_model.dart | `lib/screens/address_list/data_model/address_model.dart` | ソース | 住所データモデル |
| default_address_model.dart | `lib/screens/address_list/data_model/default_address_model.dart` | ソース | デフォルト住所設定モデル |
| index.dart | `lib/screens/address_list/utils/index.dart` | ソース | 共通インポートファイル |
