# 画面設計書 26-レビュー一覧画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおけるレビュー一覧画面の設計仕様を記述したものです。ユーザーが投稿したレビューの一覧を表示し、過去のレビュー履歴を確認できる機能を提供します。

### 本画面の処理概要

本画面は、ログイン済みユーザーが過去に投稿した商品レビューを一覧形式で表示する画面です。ページネーションによる無限スクロールに対応し、多数のレビューを効率的に閲覧できます。

**業務上の目的・背景**：ユーザーが自身の投稿履歴を確認できることは、eコマースにおける信頼性と透明性の向上に寄与します。過去のレビューを確認することで、購入履歴の振り返りや、レビューの質向上に役立ちます。また、ダッシュボードからの直接アクセスにより、アカウント管理の一部として統合されています。

**画面へのアクセス方法**：アカウント情報画面から「レビュー」をタップ、またはダッシュボードのレビューセクションからアクセスします。

**主要な操作・処理内容**：
1. 画面初期化時にレビュー一覧をAPIから取得して表示する
2. スクロールによるページネーションで追加レビューを取得する
3. 各レビューカードで商品名、評価、コメントなどを表示する

**画面遷移**：アカウント情報画面またはダッシュボードから本画面に遷移します。本画面から他画面への直接遷移はありません。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 58 | レビュー一覧表示 | 主機能 | ユーザーが投稿したレビュー一覧表示 |

## 画面種別

一覧

## URL/ルーティング

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

## 入出力項目

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

## 表示項目

### レビューカード

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 商品画像 | String | レビュー対象商品のサムネイル画像 |
| 商品名 | String | レビュー対象商品の名称 |
| 評価 | int | 星評価（1-5） |
| タイトル | String | レビューのタイトル |
| コメント | String | レビュー本文 |
| 投稿日時 | String | レビュー投稿日時 |
| ステータス | String | レビューの承認状態 |

### ページネーション情報

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| currentPage | int | 現在のページ番号 |
| lastPage | int | 最終ページ番号 |

## イベント仕様

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

画面初期化時（initState）にReviewsBlocを通じてFetchReviewsEventが発行され、レビュー一覧の取得が開始されます。

処理フロー：
1. context.read<ReviewsBloc>()でBlocインスタンスを取得
2. FetchReviewsEvent(page)を発行（初期page = 1）
3. _scrollController.addListenerでスクロール監視を設定
4. ReviewsRepository.callReviewApiが呼び出される
5. 成功時はFetchReviewStateが発行され、_reviewsListメソッドで表示

### 2-ページネーションイベント

スクロールが最下部に到達した際に追加レビューを取得します。

処理フロー：
1. paginationFunctionメソッドがスクロール位置を監視
2. maxScrollExtentに到達かつ次ページがある場合
3. pageをインクリメント
4. FetchReviewsEvent(page)を発行
5. 取得したデータを既存リストに追加

### 3-レビューリスト表示イベント

レビューデータの状態に応じたUI表示を行います。

処理フロー：
1. BlocConsumerで状態を監視
2. FetchReviewState.successの場合：
   - page > 1：既存リストに追加（reviewModel.data.addAll）
   - page = 1：新規リストとして設定
3. レビューリストが空の場合：EmptyDataViewを表示
4. レビューがある場合：ListView.builderで表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | reviews | SELECT | ログイン中ユーザーのレビュー一覧を取得 |
| ページネーション | reviews | SELECT | 追加ページのレビューを取得 |

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

#### reviews

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | customer_id = ログインユーザーID | 投稿レビュー一覧 |
| SELECT | pagination | page, limit | ページネーション情報 |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示内容 | 表示条件 |
|--------------|--------------|---------|---------|
| タイトル | StringConstants.reviews | レビュー | AppBarタイトル |
| 空データ | noReview | レビューがありません | レビュー0件時 |

## 例外処理

| 例外状況 | 処理内容 | ユーザーへの表示 |
|---------|---------|----------------|
| レビューデータなし | EmptyDataViewを表示 | 空のレビューアイコンとメッセージを表示 |
| API通信エラー | FetchReviewState.failが発行される | EmptyDataViewを表示 |
| ページネーション失敗 | 追加読み込みが停止 | 現在のリストを維持 |

## 備考

- isFromDashboardがtrueの場合、最大5件のレビューを表示し、AppBarは非表示
- ScrollControllerでスクロール位置を監視し、無限スクロールを実装
- PaginatorInfoでページネーション状態を管理（currentPage、lastPage）
- ReviewsListウィジェットで各レビューカードを表示
- ReviewLoaderウィジェットでローディング状態を表示

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | review_model.dart | `lib/data_model/review_model/review_model.dart` | ReviewModel、ReviewDataの構造を理解 |

**読解のコツ**: ReviewModelがList<ReviewData>とPaginatorInfoを持ちます。ページネーション実装の理解にPaginatorInfoの構造確認が重要です。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reviews.dart | `lib/screens/review/screen/reviews.dart` | ReviewsScreenクラスがエントリーポイント |

**主要処理フロー**:
1. **30-37行目**: initStateでBloc取得、FetchReviewsEvent発行、スクロール監視設定
2. **40-54行目**: buildメソッドでScaffold構築、isFromDashboardでAppBar表示を制御
3. **57-69行目**: BlocConsumerで状態に応じた処理
4. **72-93行目**: buildUIで状態に応じたウィジェット返却
5. **96-124行目**: _reviewsListでレビュー一覧構築
6. **126-134行目**: paginationFunctionでページネーション処理

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | reviews_list.dart | `lib/screens/review/widgets/reviews_list.dart` | レビューカードウィジェット |
| 3-2 | review_loader.dart | `lib/screens/review/widgets/review_loader.dart` | ローディング表示 |

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | review_bloc.dart | `lib/screens/review/bloc/review_bloc.dart` | イベント処理とステート発行 |
| 4-2 | review_event.dart | `lib/screens/review/bloc/review_event.dart` | FetchReviewsEventの定義 |
| 4-3 | review_state.dart | `lib/screens/review/bloc/review_state.dart` | FetchReviewStateの定義 |
| 4-4 | review_repo.dart | `lib/screens/review/bloc/review_repo.dart` | API呼び出しの実装 |

**主要処理フロー**:
- **24-33行目** (review_bloc.dart): FetchReviewsEventの処理、ページ番号を渡してAPI呼び出し

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

```
ReviewsScreen (reviews.dart)
    │
    ├─ initState()
    │      ├─ ReviewsBloc.add(FetchReviewsEvent(page))
    │      └─ _scrollController.addListener(paginationFunction)
    │
    ├─ build()
    │      ├─ AppBar (isFromDashboardで表示制御)
    │      └─ _reviewsBloc() → BlocConsumer
    │             ├─ ReviewLoader (ローディング中)
    │             ├─ EmptyDataView (データなし)
    │             └─ _reviewsList() (データあり)
    │                    └─ ListView.builder
    │                           └─ ReviewsList (各レビューカード)
    │
    ├─ paginationFunction()
    │      └─ ReviewsBloc.add(FetchReviewsEvent(page++))
    │
    └─ ReviewsBloc (review_bloc.dart)
           │
           └─ FetchReviewsEvent
                  └─ ReviewsRepository.callReviewApi(page)
                         └─ ApiClient.getReviewList(page)
```

### データフロー図

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

isFromDashboard      ───▶ ReviewsScreen.build()             ───▶ UI制御
                                 │                               (AppBar、件数)
                                 ▼
page = 1             ───▶ FetchReviewsEvent(page)           ───▶ 初期リスト表示
                                 │
                                 ▼
                         ReviewsRepository
                         .callReviewApi(page)
                                 │
                                 ▼
                         ReviewModel                         ───▶ ListView.builder
                          ├─ data[]                               │
                          └─ paginatorInfo                        ▼
                              ├─ currentPage                 ReviewsList
                              └─ lastPage

スクロール最下部     ───▶ paginationFunction()              ───▶ 追加リスト表示
                                 │
                                 ▼
                    if (currentPage < lastPage)
                                 │
                                 ▼
page++               ───▶ FetchReviewsEvent(page)
                                 │
                                 ▼
                         ReviewsRepository
                         .callReviewApi(page)
                                 │
                                 ▼
                         追加データ                          ───▶ reviewModel.data.addAll()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reviews.dart | `lib/screens/review/screen/reviews.dart` | ソース | 画面本体のStatefulWidget |
| reviews_list.dart | `lib/screens/review/widgets/reviews_list.dart` | ソース | レビューカードウィジェット |
| review_loader.dart | `lib/screens/review/widgets/review_loader.dart` | ソース | ローディング表示 |
| review_bloc.dart | `lib/screens/review/bloc/review_bloc.dart` | ソース | 状態管理Bloc |
| review_event.dart | `lib/screens/review/bloc/review_event.dart` | ソース | Blocイベント定義 |
| review_state.dart | `lib/screens/review/bloc/review_state.dart` | ソース | Blocステート定義 |
| review_repo.dart | `lib/screens/review/bloc/review_repo.dart` | ソース | API通信リポジトリ |
| index.dart | `lib/screens/review/utils/index.dart` | ソース | 共通インポートファイル |
