# 画面設計書 7-商品詳細画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリの商品詳細画面に関する設計書です。個別商品の詳細情報（画像、価格、説明、レビュー等）を表示し、カートへの追加、ウィッシュリスト・比較リストへの追加などの操作を行う画面です。

### 本画面の処理概要

**業務上の目的・背景**：商品詳細画面は、eコマースアプリにおける購買決定の最終段階で表示される重要な画面です。商品の詳細情報を提供し、ユーザーが購入判断を行うために必要なすべての情報（画像ギャラリー、価格、商品説明、レビュー、在庫状況等）を網羅的に表示します。また、商品タイプ（シンプル、コンフィギュラブル、バンドル、グループ、ダウンロード、予約商品）に応じた適切なオプション選択UIを提供します。

**画面へのアクセス方法**：
- ホーム画面の商品カルーセルから商品をタップ
- カテゴリ商品一覧画面から商品をタップ
- 検索結果一覧から商品をタップ
- ウィッシュリスト画面から商品をタップ
- カート画面から商品をタップ

**主要な操作・処理内容**：
1. 商品詳細情報の取得と表示
2. 商品画像ギャラリーの表示
3. 商品オプション（バリエーション）の選択
4. 数量の調整
5. カートへの追加
6. ウィッシュリストへの追加/削除
7. 比較リストへの追加
8. 商品のシェア
9. サンプルファイルのダウンロード（ダウンロード商品）
10. 予約スロットの選択（予約商品）
11. カスタマイズオプションの選択
12. 最近閲覧した商品への登録

**画面遷移**：
- 遷移元：ホーム画面、カテゴリ商品一覧画面、サブカテゴリ画面、検索画面、ウィッシュリスト画面、カート画面
- 遷移先：カート画面、レビュー投稿画面、比較画面

**権限による表示制御**：
- ウィッシュリスト・比較リスト操作：ログインユーザーのみ
- カートへの追加：全ユーザー可能
- 在庫なし商品：カートへの追加ボタンが非活性

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 商品詳細表示 | 主機能 | 個別商品の詳細情報・画像・価格・説明・レビュー等を表示 |
| 17 | サンプルダウンロード | 補助機能 | 商品のサンプルファイルダウンロード処理 |
| 18 | 予約スロット取得 | 補助機能 | 予約商品の利用可能スロット取得 |
| 20 | カートに追加 | 主機能 | 商品をカートに追加するボタン押下時の処理 |
| 28 | ウィッシュリストに追加 | 補助機能 | 商品をお気に入りに追加 |
| 33 | 比較リストに追加 | 補助機能 | 商品を比較リストに追加 |
| 60 | 最近閲覧した商品表示 | 補助機能 | 商品閲覧時に最近閲覧履歴へ追加 |

## 画面種別

詳細画面

## URL/ルーティング

- ルート名: `productScreen`
- パス: `/product/:urlKey`

## 入出力項目

| 項目名 | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| productId | 入力 | int | Yes | 商品ID |
| urlKey | 入力 | String | Yes | 商品URLキー |
| title | 入力 | String | No | 商品タイトル（AppBar表示用） |
| 数量 | 入力 | int | Yes | 購入数量（デフォルト1） |
| バリエーション選択 | 入力 | Map | - | コンフィギュラブル商品のオプション選択 |
| ダウンロードリンク選択 | 入力 | List | - | ダウンロード商品のリンク選択 |
| グループ商品数量 | 入力 | List | - | グループ商品の各商品数量 |
| バンドルオプション選択 | 入力 | List | - | バンドル商品のオプション選択 |
| 予約パラメータ | 入力 | Map | - | 予約商品の日時・スロット |
| カスタマイズオプション | 入力 | Map | - | カスタマイズ可能オプションの選択値 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| 商品タイトル | String | 商品名（AppBarおよび詳細セクション） |
| 商品画像ギャラリー | List<Image> | 商品画像のカルーセル |
| 価格 | String (HTML) | 価格HTML（セール価格・通常価格） |
| 商品説明 | String (HTML) | 商品の詳細説明 |
| 在庫状況 | String | 在庫あり/なしの表示 |
| 商品タイプ | String | simple/configurable/bundle/grouped/downloadable/booking |
| バリエーション選択UI | Widget | コンフィギュラブル商品のオプション |
| 数量セレクター | Widget | 数量増減ウィジェット |
| レビュー一覧 | List<Review> | 商品レビューのサマリー |
| 関連商品 | List<Product> | 関連商品の表示 |
| カートアイコンバッジ | int | カート内商品数 |
| シェアアイコン | IconButton | 商品共有ボタン |
| カートに追加ボタン | Button | カート追加ボタン（在庫なし時非活性） |

## イベント仕様

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

**トリガー**: 画面がマウントされたタイミング

**処理フロー**:
1. ログイン状態を取得（`appStoragePref.getCustomerLoggedIn()`）
2. カート数をグローバルコントローラーに通知
3. `ProductScreenBLoc`をcontext.readで取得
4. `FetchProductEvent`を送信してAPI呼び出し（urlKeyを渡す）

### 2-商品データ取得完了イベント

**トリガー**: FetchProductEventの応答受信

**処理フロー**:
1. 成功時：productDataにデータを格納、productFlatsからローカライズ情報を取得
2. 失敗時：NoInternetErrorを表示

### 3-カートに追加ボタン押下イベント

**トリガー**: 「ADD TO CART」ボタンタップ

**処理フロー**:
1. インターネット接続を確認
2. ローダー表示
3. 商品タイプに応じたバリデーション：
   - grouped: groupedParamsが空でないことを確認
   - bundle: bundleParamsが空でないことを確認
   - downloadable: downloadLinksが空でないことを確認
   - configurable: 全属性が選択されていることを確認
   - booking: 予約パラメータが正しく設定されていることを確認
4. カスタマイズオプションの必須チェック
5. `AddToCartProductEvent`を送信
6. 成功時：成功メッセージ表示、カート数更新
7. 失敗時：エラーメッセージ表示

### 4-ウィッシュリスト追加/削除イベント

**トリガー**: ウィッシュリストアイコンタップ

**処理フロー**:
1. ログイン状態を確認
2. 未ログインの場合：警告メッセージを表示
3. ログイン済みの場合：
   - ウィッシュリストに存在する場合：削除イベント送信
   - 存在しない場合：追加イベント送信
4. 結果に応じてメッセージを表示

### 5-比較リスト追加イベント

**トリガー**: 比較アイコンタップ

**処理フロー**:
1. ログイン状態を確認
2. 未ログインの場合：警告メッセージを表示
3. ログイン済みの場合：`AddToCompareListEvent`を送信
4. 結果に応じてメッセージを表示

### 6-シェアボタン押下イベント

**トリガー**: シェアアイコンタップ

**処理フロー**:
1. `Share.share()`を呼び出し
2. productData.shareURLを共有

### 7-戻るボタン押下イベント

**トリガー**: バックボタンタップ

**処理フロー**:
1. `setRecentViewed()`で閲覧履歴に追加
2. Hiveデータベースに商品データを保存
3. `Navigator.pop()`で前の画面に戻る

### 8-サンプルダウンロードイベント

**トリガー**: サンプルダウンロードボタンタップ

**処理フロー**:
1. `DownloadProductSampleEvent`を送信
2. 成功時：Base64文字列をファイルとして保存
3. 失敗時：エラーメッセージ表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| カートに追加 | cart_items (サーバー側) | INSERT/UPDATE | 商品をカートに追加 |
| ウィッシュリストに追加 | wishlist_items (サーバー側) | INSERT | 商品をウィッシュリストに追加 |
| ウィッシュリストから削除 | wishlist_items (サーバー側) | DELETE | 商品をウィッシュリストから削除 |
| 比較リストに追加 | compare_items (サーバー側) | INSERT | 商品を比較リストに追加 |
| 最近閲覧に追加 | recentProducts (Hive) | PUT | 商品データをローカルに保存 |

### Hive更新項目

| 操作 | Box名 | キー | 値 | 備考 |
|-----|-------|------|-----|------|
| 閲覧履歴追加 | recentProducts | productData.id | NewProductsオブジェクト | 画面離脱時に保存 |

## メッセージ仕様

| メッセージID | メッセージ種別 | 表示条件 | メッセージ内容 |
|-------------|--------------|----------|--------------|
| MSG-001 | 成功 | カート追加成功 | APIから返却されるメッセージ |
| MSG-002 | エラー | カート追加失敗 | エラーメッセージ |
| MSG-003 | 警告 | グループ商品数量未選択 | 「Please select at least one product」 |
| MSG-004 | 警告 | バンドルオプション未選択 | 「Please select at least one option」 |
| MSG-005 | 警告 | ダウンロードリンク未選択 | 「Link is required」 |
| MSG-006 | 警告 | バリエーション未選択 | 「Please select all variants」 |
| MSG-007 | 警告 | ネットワークエラー | 「Internet connection issue」 |
| MSG-008 | 成功 | ウィッシュリスト追加成功 | APIから返却されるメッセージ |
| MSG-009 | 成功 | 比較リスト追加成功 | APIから返却されるメッセージ |
| MSG-010 | 警告 | 未ログイン | 「Please login」 |
| MSG-011 | 警告 | カスタマイズオプション未入力 | 「{オプション名} is required」 |

## 例外処理

| 例外ケース | 処理内容 | ユーザーへの影響 |
|-----------|---------|----------------|
| 商品データ取得失敗 | NoInternetErrorを表示 | 商品情報が表示されない |
| カート追加失敗 | エラーメッセージを表示、ローダー非表示 | カートに追加されない |
| 在庫なし | カート追加ボタンを非活性（opacity: 0.2） | カートに追加できない |
| サンプルダウンロード失敗 | エラーメッセージを表示 | ファイルがダウンロードされない |

## 備考

- 商品タイプに応じて異なるUI/UXを提供（configurable, bundle, grouped, downloadable, booking）
- カスタマイズオプションはファイルアップロードにも対応
- 予約商品はテーブル予約、イベント予約など複数タイプに対応
- 最近閲覧した商品はHiveデータベースに保存
- シェア機能はshare_plusパッケージを使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | new_product_data.dart | `lib/screens/home_page/data_model/new_product_data.dart` | 商品データモデルの構造 |
| 1-2 | booking_slots_modal.dart | `lib/data_model/product_model/booking_slots_modal.dart` | 予約スロットデータモデル |
| 1-3 | download_sample_model.dart | `lib/screens/product_screen/data_model/download_sample_model.dart` | サンプルダウンロードモデル |

**読解のコツ**: NewProductsモデルにはtype, configurableData, bundleOptions, groupedProducts, downloadableLinks, booking, customizableOptionsなど商品タイプに応じたフィールドがある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | product_screen.dart | `lib/screens/product_screen/view/product_screen.dart` | 商品詳細画面のメインウィジェット |

**主要処理フロー**:
1. **58-65行目**: `initState()`でログイン状態取得、FetchProductEvent送信
2. **68-112行目**: `build()`でScaffoldとAppBar構築
3. **152-197行目**: `_setProductData()`でBlocConsumer構築
4. **200-338行目**: `buildContainer()`で各状態に応じたUI構築
5. **340-581行目**: `_addToCart()`で商品タイプ別のカート追加処理
6. **671-678行目**: `setRecentViewed()`で閲覧履歴保存

#### Step 3: Blocレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | product_screen_bloc.dart | `lib/screens/product_screen/bloc/product_screen_bloc.dart` | 状態管理Bloc |
| 3-2 | product_screen_event.dart | `lib/screens/product_screen/bloc/product_screen_event.dart` | イベント定義 |

**主要処理フロー**:
- `FetchProductEvent`: 商品詳細API呼び出し
- `AddToCartProductEvent`: カート追加API呼び出し
- `AddToWishListProductEvent`: ウィッシュリスト追加
- `AddToCompareListEvent`: 比較リスト追加

#### Step 4: ビューレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | product_view.dart | `lib/screens/product_screen/view/widget/product_view.dart` | 商品詳細ビュー本体 |

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

```
ProductScreen (StatefulWidget)
    │
    ├─ initState()
    │      ├─ appStoragePref.getCustomerLoggedIn()
    │      ├─ ProductScreenBLoc (context.read)
    │      └─ ProductScreenBLoc.add(FetchProductEvent)
    │
    ├─ build()
    │      └─ Scaffold
    │             ├─ AppBar
    │             │      ├─ IconButton (back) → setRecentViewed() → Navigator.pop()
    │             │      ├─ IconButton (share) → Share.share()
    │             │      └─ BadgeIcon (cart)
    │             └─ _setProductData() → BlocConsumer<ProductScreenBLoc>
    │                    └─ buildContainer()
    │                           ├─ ProductDetailLoader (初期状態)
    │                           └─ ProductView + ADD TO CARTボタン
    │
    ├─ _addToCart()
    │      ├─ checkInternetConnection()
    │      ├─ カスタマイズオプション必須チェック
    │      ├─ 商品タイプ別バリデーション
    │      │      ├─ grouped: groupedParamsチェック
    │      │      ├─ bundle: bundleParamsチェック
    │      │      ├─ downloadable: downloadLinksチェック
    │      │      ├─ configurable: configurableParamsチェック
    │      │      └─ booking: bookingParamsチェック
    │      └─ ProductScreenBLoc.add(AddToCartProductEvent)
    │
    └─ setRecentViewed()
           └─ Hive.openBox("recentProducts").put()
```

### データフロー図

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

urlKey ─────────────────▶ FetchProductEvent ────────────▶ NewProducts
                                │
                                ▼
                         ProductView表示
                                │
ユーザー選択 ───────────────────┤
  ├─ バリエーション ────────────┤
  ├─ 数量 ──────────────────────┤
  ├─ ダウンロードリンク ────────┤
  ├─ バンドルオプション ────────┤
  ├─ カスタマイズオプション ────┤
  └─ 予約パラメータ ────────────┘
                                │
                                ▼
                         _addToCart()
                                │
                                ▼
                         AddToCartProductEvent
                                │
                                ▼
                         カート数更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| product_screen.dart | `lib/screens/product_screen/view/product_screen.dart` | ソース | 商品詳細画面のメインウィジェット |
| product_view.dart | `lib/screens/product_screen/view/widget/product_view.dart` | ソース | 商品詳細ビュー本体 |
| product_screen_bloc.dart | `lib/screens/product_screen/bloc/product_screen_bloc.dart` | ソース | 状態管理Bloc |
| product_screen_event.dart | `lib/screens/product_screen/bloc/product_screen_event.dart` | ソース | イベント定義 |
| product_screen_state.dart | `lib/screens/product_screen/bloc/product_screen_state.dart` | ソース | 状態定義 |
| product_screen_repository.dart | `lib/screens/product_screen/bloc/product_screen_repository.dart` | ソース | API通信処理 |
| new_product_data.dart | `lib/screens/home_page/data_model/new_product_data.dart` | ソース | 商品データモデル |
| booking_slots_modal.dart | `lib/data_model/product_model/booking_slots_modal.dart` | ソース | 予約スロットモデル |
| download_sample_model.dart | `lib/screens/product_screen/data_model/download_sample_model.dart` | ソース | サンプルダウンロードモデル |
| index.dart | `lib/screens/product_screen/utils/index.dart` | ソース | エクスポート集約 |
| route_constants.dart | `lib/utils/route_constants.dart` | ソース | ルーティング定数 |
