# 機能設計書 27-ウィッシュリスト表示

## 概要

本ドキュメントは、ECモバイルアプリにおけるウィッシュリスト（お気に入り商品一覧）の表示機能について設計仕様を定義する。

### 本機能の処理概要

本機能は、ユーザーがお気に入り登録した商品の一覧を表示し、商品の管理や購入検討を支援する機能である。

**業務上の目的・背景**：ECサイトにおいて、ウィッシュリスト機能はユーザーの購入検討をサポートする重要な機能である。気になる商品を一覧で管理し、後で購入を決定する際の参考にできる。また、価格変動やセール時に購入を判断する際のリマインダーとしても機能する。

**機能の利用シーン**：ユーザーが過去にお気に入り登録した商品を確認したい場合、購入を検討中の商品を比較したい場合、またはウィッシュリストからカートに商品を追加したい場合に利用される。

**主要な処理内容**：
1. ウィッシュリスト画面を開く
2. GraphQL API経由でウィッシュリストデータを取得
3. 商品情報をグリッド形式で一覧表示
4. 各商品に対して「カートに追加」「削除」操作を提供
5. 商品タップで商品詳細画面に遷移
6. カート数をヘッダーに表示

**関連システム・外部連携**：Bagisto GraphQL APIとの連携により、ウィッシュリストデータを取得する。

**権限による制御**：ログインユーザーのみ利用可能。ウィッシュリストはユーザーアカウントに紐づく。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | ウィッシュリスト画面 | 主画面 | お気に入り商品一覧の表示 |

## 機能種別

CRUD操作（Read）/ 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | パラメータ不要（認証で特定） | - |

### 入力データソース

画面遷移（ナビゲーションからウィッシュリスト画面を開く）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | List<WishlistData> | ウィッシュリスト商品リスト |
| data[].id | String | ウィッシュリストエントリID |
| data[].productId | String | 商品ID |
| data[].product | Product | 商品詳細情報 |
| data[].product.name | String | 商品名 |
| data[].product.images | List | 商品画像リスト |
| data[].product.priceHtml | PriceHtml | 価格HTML情報 |
| data[].product.isSaleable | bool | 購入可否 |

### 出力先

- 画面表示（グリッド形式で商品一覧を表示）
- ヘッダーにカート数バッジを表示

## 処理フロー

### 処理シーケンス

```
1. ウィッシュリスト画面を表示
   └─ initStateでFetchWishListEventを発行
2. WishListBlocがイベントを受信
   └─ repository.callWishListApiを呼び出し
3. WishListRepositoryがApiClientを経由でAPI呼び出し
   └─ GraphQL query wishlists/getWishlistを実行
4. 成功時: FetchDataState.successを発行
   └─ ウィッシュリストデータを画面に渡す
5. WishlistItemListでグリッド表示
   └─ 各商品を2列グリッドで表示
6. 空の場合: EmptyDataViewを表示
```

### フローチャート

```mermaid
flowchart TD
    A[画面表示] --> B[FetchWishListEvent発行]
    B --> C[WishListBloc処理]
    C --> D[API呼び出し]
    D --> E{成功?}
    E -->|Yes| F[FetchDataState.success]
    F --> G{データあり?}
    G -->|Yes| H[WishlistItemListで一覧表示]
    G -->|No| I[EmptyDataView表示]
    E -->|No| J[FetchDataState.fail]
    J --> K[エラー表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-027-01 | ログイン必須 | ウィッシュリスト表示はログインユーザーのみ | 画面アクセス時 |
| BR-027-02 | グリッド表示 | 商品は2列グリッド形式で表示 | 一覧表示時 |
| BR-027-03 | 購入可否表示 | 購入不可商品は「カートに追加」ボタンをグレーアウト | 一覧表示時 |
| BR-027-04 | 空表示 | ウィッシュリストが空の場合は専用メッセージを表示 | データなし時 |

### 計算ロジック

特になし（表示のみ）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ウィッシュリスト取得 | wishlists | SELECT | ログインユーザーのウィッシュリストを取得 |
| 商品情報取得 | products | SELECT | 関連商品の詳細情報を取得 |

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

#### wishlists

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, product_id | customer_id = ログインユーザー | 関連商品情報も結合取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ネットワークエラー | API通信失敗 | EmptyDataView表示 |
| - | 認証エラー | セッション切れ | エラー表示 |

### リトライ仕様

自動リトライは行わない。ユーザーがプルトゥリフレッシュで再取得可能。

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

読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- API応答時間: 2秒以内を目標
- 画像読み込み: 遅延読み込み（LazyLoading）

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

- 認証: ログインユーザーのみアクセス可能
- データアクセス: 自身のウィッシュリストのみ表示

## 備考

ウィッシュリスト画面には「全削除」用のFloatingActionButtonがあり、商品数が1以上の場合に表示される。

---

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

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

### 推奨読解順序

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

ウィッシュリストのデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | wishlist_model.dart | `lib/screens/wishList/data_model/wishlist_model.dart` | WishListData、WishlistDataクラスの構造 |
| 1-2 | product_details_model.dart | `lib/screens/product_screen/data_model/product_details_model.dart` | Productクラス（ウィッシュリストに含まれる商品情報） |

**読解のコツ**: WishListDataはWishlistDataのリストを持ち、各WishlistDataはProductを参照する入れ子構造。

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

画面初期化からデータ取得までの流れを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | wishlist_screen.dart | `lib/screens/wishList/view/wishlist_screen.dart` | initState、FetchWishListEvent発行、BlocConsumer |

**主要処理フロー**:
1. **32-39行目**: initStateでカート数取得とFetchWishListEvent発行
2. **53-97行目**: Scaffold構築、AppBar、FloatingActionButton
3. **115-168行目**: BlocConsumerでの状態管理とUI構築
4. **171-232行目**: buildContainerで状態に応じたUI分岐

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

状態管理とビジネスロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | wishlist_event.dart | `lib/screens/wishList/bloc/wishlist_event.dart` | FetchWishListEventの定義（15-16行目） |
| 3-2 | wishlist_state.dart | `lib/screens/wishList/bloc/wishlist_state.dart` | FetchDataStateの定義（23-31行目） |
| 3-3 | wishlist_bloc.dart | `lib/screens/wishList/bloc/wishlist_bloc.dart` | FetchWishListEventの処理（24-36行目） |

**主要処理フロー**:
- **24-36行目**: FetchWishListEventを受信し、repository経由でAPI呼び出し、status判定で状態分岐

#### Step 4: リポジトリ層とAPI層を理解する

実際のAPI呼び出し処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | wishlist_repository.dart | `lib/screens/wishList/bloc/wishlist_repository.dart` | callWishListApiメソッド（26-35行目） |
| 4-2 | api_client.dart | `lib/services/api_client.dart` | getWishList API呼び出し |

#### Step 5: 一覧表示UIを理解する

実際の商品リスト表示を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | wishlist_Item_list.dart | `lib/screens/wishList/view/widget/wishlist_Item_list.dart` | GridView.builder、商品カード、各種ボタン |

**主要処理フロー**:
1. **38-45行目**: GridView.builderで2列グリッド構築
2. **48-59行目**: 商品タップで詳細画面へ遷移
3. **71-113行目**: 商品画像と削除ボタン
4. **149-200行目**: カートに追加ボタンと処理

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

```
WishListScreen (wishlist_screen.dart)
    │
    └─ initState
           │
           └─ FetchWishListEvent発行
                  │
                  └─ WishListBloc.mapEventToState
                         │
                         └─ WishListRepository.callWishListApi
                                │
                                └─ ApiClient.getWishList
                                       │
                                       └─ GraphQL Query
                                              │
                                              ▼
                               WishListData ───▶ FetchDataState ───▶ WishlistItemList
                                 (応答)            (状態)            (UI表示)
```

### データフロー図

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

画面表示 ───▶ FetchWishListEvent ───▶ WishListBloc
 (遷移)       (イベント発行)           (状態管理)
                                            │
                      ┌─────────────────────┘
                      ▼
            WishListRepository
                      │
                      ▼
                ApiClient
                      │
                      ▼
             GraphQL API (wishlists)
                      │
                      ▼
             WishListData ───▶ FetchDataState ───▶ WishlistItemList
               (応答)           (状態通知)         (グリッド表示)
                                                       │
                                                       ▼
                                            商品タップ → 商品詳細画面
                                            カート追加 → カートAPI
                                            削除 → 削除API
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| wishlist_screen.dart | `lib/screens/wishList/view/wishlist_screen.dart` | ソース | ウィッシュリスト画面メインWidget |
| wishlist_Item_list.dart | `lib/screens/wishList/view/widget/wishlist_Item_list.dart` | ソース | 商品リスト表示Widget |
| wishlist_loader.dart | `lib/screens/wishList/view/widget/wishlist_loader.dart` | ソース | ローディング表示Widget |
| wishlist_bloc.dart | `lib/screens/wishList/bloc/wishlist_bloc.dart` | ソース | ウィッシュリストBLoC |
| wishlist_event.dart | `lib/screens/wishList/bloc/wishlist_event.dart` | ソース | BLoCイベント定義 |
| wishlist_state.dart | `lib/screens/wishList/bloc/wishlist_state.dart` | ソース | BLoC状態定義 |
| wishlist_repository.dart | `lib/screens/wishList/bloc/wishlist_repository.dart` | ソース | ウィッシュリストリポジトリ |
| wishlist_model.dart | `lib/screens/wishList/data_model/wishlist_model.dart` | ソース | ウィッシュリストデータモデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント |
