# 機能設計書 58-レビュー一覧表示

## 概要

本ドキュメントは、ユーザーが投稿したレビュー一覧を表示する機能の設計を記述する。

### 本機能の処理概要

本機能は、ログイン済みユーザーが過去に投稿した商品レビューの一覧を表示する機能を提供する。レビューには評価（星）、タイトル、コメント、投稿日時などの情報が含まれ、ページネーションによる大量データの効率的な表示に対応している。

**業務上の目的・背景**：ユーザーが自身の投稿したレビューを一覧で確認できることは、購入履歴の振り返りやレビュー管理の観点から重要である。また、レビュー投稿を促進するため、過去の投稿を可視化することでユーザーエンゲージメントを高める効果も期待できる。

**機能の利用シーン**：アカウント管理画面からレビュー一覧へ遷移時、ダッシュボードのレビュータブ表示時、自身の投稿履歴を確認したい時などにユーザーが利用する。

**主要な処理内容**：
1. バックエンドAPIからユーザーのレビュー一覧を取得
2. レビューデータをリスト形式で表示
3. ページネーションによる追加データの取得
4. ダッシュボードからの表示時は最大5件に制限

**関連システム・外部連携**：GraphQL APIを介してバックエンドサーバーからレビューデータを取得。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | レビュー一覧画面 | 主画面 | ユーザーが投稿したレビュー一覧表示 |
| 3 | ダッシュボード画面 | 参照画面 | ダッシュボードのレビュータブとして表示 |

## 機能種別

データ表示（CRUD - Read）/ ページネーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| isFromDashboard | bool | No | ダッシュボードからの表示かどうか | - |
| page | int | Yes | 取得するページ番号 | 1以上 |

### 入力データソース

- 画面遷移パラメータ
- スクロールイベント（ページネーション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | List<ReviewData> | レビューデータリスト |
| data[].id | String | レビューID |
| data[].title | String | レビュータイトル |
| data[].comment | String | レビューコメント |
| data[].rating | int | 評価（1-5） |
| data[].status | String | ステータス（approved等） |
| data[].createdAt | String | 投稿日時 |
| data[].product | Product | 関連商品情報 |
| paginatorInfo | PaginatorInfo | ページネーション情報 |
| paginatorInfo.currentPage | int | 現在のページ番号 |
| paginatorInfo.lastPage | int | 最終ページ番号 |

### 出力先

画面表示（レビュー一覧画面）

## 処理フロー

### 処理シーケンス

```
1. 画面初期化
   └─ ReviewsBlocの初期化とFetchReviewsEvent(page=1)の発行
2. API呼び出し
   └─ ReviewsRepositoryImp.callReviewApi()でGraphQL APIを呼び出し
3. レスポンス処理
   └─ ReviewModelにデータをマッピング
4. 状態更新
   └─ FetchReviewState.successで成功状態を発行
5. UI更新
   └─ _reviewsListメソッドでリストをListViewで表示
6. スクロール検知
   └─ 末尾到達時にpaginationFunctionで次ページ取得
```

### フローチャート

```mermaid
flowchart TD
    A[画面初期化] --> B[FetchReviewsEvent page=1 発行]
    B --> C[API呼び出し]
    C --> D{レスポンス}
    D -->|成功| E[レビューデータ取得]
    D -->|失敗| F[エラー画面表示]
    E --> G{レビューあり?}
    G -->|Yes| H[レビュー一覧表示]
    G -->|No| I[空データビュー表示]
    H --> J[ユーザースクロール]
    J --> K{末尾到達?}
    K -->|Yes| L{次ページあり?}
    L -->|Yes| M[FetchReviewsEvent page++ 発行]
    M --> C
    L -->|No| N[処理終了]
    K -->|No| J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | ダッシュボード表示制限 | ダッシュボードからの表示時は最大5件まで | isFromDashboard=true |
| BR-58-02 | ページネーション | スクロール末尾到達時に次ページを自動取得 | 全件表示画面 |
| BR-58-03 | データ追加方式 | 2ページ目以降は既存データに追加 | page > 1 |
| BR-58-04 | 空データ表示 | レビューがない場合は専用の空データビューを表示 | データ0件時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| レビュー取得 | product_reviews | SELECT | ユーザーの投稿レビューを取得 |

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

#### product_reviews

| 操作 | 項目（カラム名） | 取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, title, comment, rating, status, created_at, product_id | customer_id = ログインユーザーID | ページネーション付き |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

画面を再度開くことで再取得が可能。ページネーション中のエラーは次回スクロール時に再試行。

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

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

## パフォーマンス要件

- 一覧表示: 2秒以内
- ページネーション: 1秒以内
- ListViewでの効率的なリスト描画
- ScrollControllerでスクロール位置を監視

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

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

## 備考

- BlocConsumerパターンで状態管理
- ページネーション情報はReviewModel.paginatorInfoで管理
- ダッシュボード画面ではAppBarを非表示

---

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

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

### 推奨読解順序

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

レビューデータのモデル構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | review_state.dart | `lib/screens/review/bloc/review_state.dart` | ReviewModel, FetchReviewStateの構造 |

**読解のコツ**: ReviewModelはdata（レビューリスト）とpaginatorInfo（ページネーション情報）を保持。FetchReviewStateはstatus（success/fail）でAPI結果を管理。

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

レビュー一覧画面のメインウィジェットを確認する。

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

**主要処理フロー**:
1. **30-36行目**: initStateでReviewsBlocを取得し、FetchReviewsEventを発行、スクロールリスナーを設定
2. **57-69行目**: BlocConsumerでリスナーとビルダーを設定
3. **72-93行目**: buildUIメソッドで状態に応じたUI構築
4. **96-124行目**: _reviewsListメソッドでレビュー一覧を表示
5. **126-134行目**: paginationFunctionでスクロール末尾検知と次ページ取得

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

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

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

**主要処理フロー**:
- **22-34行目** (review_bloc.dart): FetchReviewsEventの処理
- **17-22行目** (review_event.dart): FetchReviewsEventの定義
- **26-39行目** (review_state.dart): FetchReviewStateの定義

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

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

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

**主要処理フロー**:
- **19-31行目**: callReviewApiメソッドでApiClient().getReviewList(page)を呼び出し

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

```
ReviewsScreen (reviews.dart)
    │
    ├─ ReviewsBloc (review_bloc.dart)
    │      │
    │      └─ ReviewsRepositoryImp (review_repo.dart)
    │             │
    │             └─ ApiClient.getReviewList(page)
    │                    │
    │                    └─ GraphQL API
    │
    ├─ ReviewsList (reviews_list.dart)
    │      └─ レビューカード表示
    │
    └─ ScrollController
           └─ paginationFunction()
                  └─ FetchReviewsEvent(page++)
```

### データフロー図

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

FetchReviewsEvent ───▶ ReviewsBloc ───▶ FetchReviewState
(page)                       │
                             ▼
                   ReviewsRepositoryImp
                             │
                             ▼
                   ApiClient.getReviewList(page)
                             │
                             ▼
                       GraphQL API
                             │
                             ▼
                       ReviewModel
                             │
                             ├─ page == 1 → 新規データ設定
                             └─ page > 1 → 既存データに追加
                             │
                             ▼
                   ReviewsScreen ───▶ レビューカード一覧

[スクロール]
末尾到達 ───▶ paginationFunction()
                   │
                   ▼
         次ページあり? ───▶ FetchReviewsEvent(page++)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reviews.dart | `lib/screens/review/screen/reviews.dart` | ソース | メイン画面 |
| review_bloc.dart | `lib/screens/review/bloc/review_bloc.dart` | ソース | 状態管理 |
| review_repo.dart | `lib/screens/review/bloc/review_repo.dart` | ソース | API呼び出し |
| review_event.dart | `lib/screens/review/bloc/review_event.dart` | ソース | イベント定義 |
| review_state.dart | `lib/screens/review/bloc/review_state.dart` | ソース | ステート定義 |
| reviews_list.dart | `lib/screens/review/widgets/reviews_list.dart` | ソース | レビューカードウィジェット |
| review_loader.dart | `lib/screens/review/widgets/review_loader.dart` | ソース | ローディング表示 |
