# 機能設計書 52-住所一覧表示

## 概要

本ドキュメントは、ユーザーが登録した住所の一覧を表示する機能の設計を記述する。

### 本機能の処理概要

本機能は、ログイン済みユーザーが登録した配送先・請求先住所の一覧を表示する。ユーザーは一覧から住所の編集、削除、デフォルト住所の設定が可能であり、新規住所の追加画面への遷移も提供される。

**業務上の目的・背景**：ECサイトでの購入プロセスにおいて、配送先住所の管理は重要な機能である。ユーザーが複数の住所を登録・管理できることで、注文時の利便性が向上し、配送ミスの軽減にも貢献する。また、デフォルト住所の設定により、チェックアウト時の入力負荷を軽減できる。

**機能の利用シーン**：アカウント管理画面から住所一覧へ遷移時、チェックアウト時の住所選択時、ダッシュボードの住所タブ表示時などにユーザーが利用する。

**主要な処理内容**：
1. バックエンドAPIから登録済み住所一覧を取得
2. 住所データをカード形式で一覧表示
3. 各住所カードに編集・削除ボタンを提供
4. デフォルト住所の設定・表示
5. 新規住所追加ボタンの表示
6. プルダウンによる一覧更新

**関連システム・外部連携**：GraphQL APIを介してバックエンドサーバーから住所データを取得。住所変更はリアルタイムでサーバーと同期される。

**権限による制御**：ログイン済みユーザーのみがアクセス可能。自身の住所データのみ表示・操作可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | 住所一覧画面 | 主画面 | 登録済み住所の一覧表示 |
| 3 | ダッシュボード画面 | 参照画面 | ダッシュボードの住所タブとして表示 |
| 15 | チェックアウト住所選択画面 | 参照画面 | チェックアウト時の住所選択一覧 |

## 機能種別

データ表示（CRUD - Read）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| isFromDashboard | bool | No | ダッシュボードからの表示かどうか | - |

### 入力データソース

- GraphQL API: getAddressData()

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| addressData | List<AddressData> | 住所データリスト |
| addressData[].id | String | 住所ID |
| addressData[].firstName | String | 名（ファーストネーム） |
| addressData[].lastName | String | 姓（ラストネーム） |
| addressData[].email | String | メールアドレス |
| addressData[].companyName | String | 会社名 |
| addressData[].vatId | String | VAT ID |
| addressData[].address1 | String | 住所1 |
| addressData[].country | String | 国コード |
| addressData[].countryName | String | 国名 |
| addressData[].stateName | String | 州名 |
| addressData[].state | String | 州コード |
| addressData[].city | String | 市区町村 |
| addressData[].postcode | String | 郵便番号 |
| addressData[].phone | String | 電話番号 |
| addressData[].isDefault | bool | デフォルト住所フラグ |

### 出力先

画面表示（住所一覧画面）

## 処理フロー

### 処理シーケンス

```
1. 画面初期化
   └─ AddressBlocの初期化とFetchAddressEventの発行
2. API呼び出し
   └─ AddressRepositoryImp.callAddressApi()でGraphQL APIを呼び出し
3. レスポンス処理
   └─ AddressModelにデータをマッピング
4. 状態更新
   └─ FetchAddressState.successで成功状態を発行
5. UI更新
   └─ _addressListメソッドで一覧をListViewで表示
6. ユーザー操作待機
   └─ 編集、削除、デフォルト設定の操作を受付
```

### フローチャート

```mermaid
flowchart TD
    A[画面初期化] --> B[FetchAddressEvent発行]
    B --> C[API呼び出し]
    C --> D{レスポンス}
    D -->|成功| E[住所データ取得]
    D -->|失敗| F[エラー画面表示]
    E --> G{住所あり?}
    G -->|Yes| H[住所一覧表示]
    G -->|No| I[空データビュー表示]
    H --> J[ユーザー操作]
    J -->|編集| K[編集画面遷移]
    J -->|削除| L[削除確認ダイアログ]
    J -->|デフォルト設定| M[デフォルト設定API呼出]
    L -->|Yes| N[削除API呼出]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | ダッシュボード表示制限 | ダッシュボードからの表示時は最大5件まで | isFromDashboard=true |
| BR-52-02 | デフォルト住所ボタン | デフォルト住所の場合は「Default」、それ以外は「Set Default」を表示 | 常時 |
| BR-52-03 | 住所フォーマット | 「住所, 市区町村, 州名, 国名, 郵便番号」の形式で表示 | 常時 |
| BR-52-04 | 削除確認 | 削除前に確認ダイアログを表示 | 削除操作時 |
| BR-52-05 | 新規追加ボタン | ダッシュボードからの表示時は新規追加ボタンを非表示 | isFromDashboard=true |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | customer_addresses | SELECT | ユーザーの登録住所を取得 |

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

#### customer_addresses

| 操作 | 項目（カラム名） | 取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, firstName, lastName, email, companyName, vatId, address, country, countryName, stateName, state, city, postcode, phone, defaultAddress | customer_id = ログインユーザーID | ログインユーザーの住所のみ取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API通信エラー | ネットワーク障害 | EmptyDataViewを表示 |
| - | 認証エラー | トークン期限切れ | ログイン画面へ遷移 |

### リトライ仕様

RefreshIndicatorによるプルダウン更新で再取得可能。更新は1秒のディレイ後にFetchAddressEventを再発行。

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

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

## パフォーマンス要件

- 一覧表示: 2秒以内
- RefreshIndicator使用でスムーズなリロード
- ListViewでの効率的なリスト描画

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

- ログイン済みユーザーのみアクセス可能
- 認証トークン付きでAPIリクエスト送信
- 自身の住所データのみ取得・表示可能

## 備考

- BlocConsumerパターンで状態管理
- 住所データはローカルにもキャッシュ（appStoragePref.setAddressData）
- ダッシュボードからの表示時はisFromDashboardフラグで表示制御

---

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

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

### 推奨読解順序

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

住所データのモデル構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address_model.dart | `lib/screens/address_list/data_model/address_model.dart` | AddressModel, AddressDataクラスの構造 |

**読解のコツ**: AddressModelはBaseModelを継承し、addressDataリストを保持。各AddressDataは住所の詳細情報を持つ。@JsonSerializableでJSON変換対応。

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

住所一覧画面のメインウィジェットを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | address_screen.dart | `lib/screens/address_list/view/address_screen.dart` | 画面構築とBloc連携ロジック |

**主要処理フロー**:
1. **31-34行目**: initStateでAddressBlocを取得し、FetchAddressEventを発行
2. **54-84行目**: BlocConsumerでリスナーとビルダーを設定
3. **88-118行目**: buildUIメソッドで状態に応じたUI構築
4. **122-228行目**: _addressListメソッドで住所一覧を表示

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

状態管理のロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | イベント処理とステート発行 |
| 3-2 | address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | イベント定義 |
| 3-3 | address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | ステート定義 |

**主要処理フロー**:
- **24-30行目** (address_bloc.dart): FetchAddressEventの処理
- **14-16行目** (address_event.dart): FetchAddressEventの定義
- **38-48行目** (address_state.dart): FetchAddressStateの定義

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

API呼び出しのロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | API呼び出し実装 |

**主要処理フロー**:
- **28-37行目**: callAddressApiメソッドでApiClient().getAddressData()を呼び出し

#### Step 5: UIコンポーネントを理解する

住所カードのUI構築を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | saved_address_list.dart | `lib/screens/address_list/view/widget/saved_address_list.dart` | 住所カードウィジェット |

**主要処理フロー**:
- **23-194行目**: 住所カードのUI構築
- **66-70行目**: デフォルト住所設定の処理
- **118-127行目**: 編集ボタンの処理
- **163-167行目**: 削除ボタンの処理

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

```
AddressScreen (address_screen.dart)
    │
    ├─ AddressBloc (address_bloc.dart)
    │      │
    │      └─ AddressRepositoryImp (address_repository.dart)
    │             │
    │             └─ ApiClient.getAddressData()
    │
    ├─ SavedAddressList (saved_address_list.dart)
    │      │
    │      ├─ 編集ボタン → Navigator.pushNamed(addAddressScreen)
    │      └─ 削除ボタン → AddressBloc.add(RemoveAddressEvent)
    │
    └─ AddNewAddressButton (add_new_address_button.dart)
```

### データフロー図

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

FetchAddressEvent ───▶ AddressBloc ───▶ FetchAddressState
                              │
                              ▼
                    AddressRepositoryImp
                              │
                              ▼
                    ApiClient.getAddressData()
                              │
                              ▼
                       GraphQL API
                              │
                              ▼
                    AddressModel ───▶ AddressScreen ───▶ 住所カード一覧
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| address_screen.dart | `lib/screens/address_list/view/address_screen.dart` | ソース | メイン画面 |
| address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | ソース | 状態管理 |
| address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | ソース | API呼び出し |
| address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | ソース | イベント定義 |
| address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | ソース | ステート定義 |
| address_model.dart | `lib/screens/address_list/data_model/address_model.dart` | ソース | データモデル |
| 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` | ソース | ローディング表示 |
