# 通知設計書 9-全カート商品削除成功通知

## 概要

本ドキュメントは、Bagisto ECモバイルアプリにおけるカート内の全商品を一括削除した際に表示される成功通知の設計書である。

### 本通知の処理概要

本通知は、ユーザーがショッピングカート内のすべての商品を一括削除した操作が正常に完了した際に、緑色のオーバーレイ通知を画面上部に表示し、削除成功をフィードバックする機能を提供する。

**業務上の目的・背景**：ECアプリにおいて、ユーザーが購入を取りやめる場合やカートをリセットしたい場合に、全商品を一括で削除する機能は利便性が高い。この一括削除操作が正常に完了したことをユーザーに明確にフィードバックすることで、ユーザーは操作が正しく反映されたことを確認できる。個別削除（No.8）とは異なり、全商品が削除されたことを示す重要なフィードバックとなる。

**通知の送信タイミング**：カート画面で「全削除」ボタンをタップし、サーバーへの全削除リクエストが成功した直後。BLoCパターンにおいて `RemoveAllCartItemState.success` が emit された時点で通知が表示される。

**通知の受信者**：カート画面で全商品削除操作を実行したユーザー本人。

**通知内容の概要**：「Success」タイトルと、サーバーから返却された全削除完了メッセージ（`removeAllCartProductModel.message`）を表示。緑色の背景とチェックマークアイコン。

**期待されるアクション**：ユーザーは通知を確認し、カートが空になったことを確認する。その後、商品ブラウジングに戻るか、アプリを終了する。

## 通知種別

アプリ内通知（オーバーレイ通知 / 成功通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（BLoC状態変化時に即座表示） |
| 優先度 | 中 |
| リトライ | なし |

### 送信先決定ロジック

1. カート画面で全削除操作を実行したユーザーに対してのみ表示
2. `BlocConsumer` の `listener` で状態変化を検出
3. `RemoveAllCartItemState` で `CartStatus.success` の場合に通知

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 画面上部 |
| 背景色 | Colors.green.shade400 |
| アイコン | Icons.check_circle_outline（白色） |
| 消去方向 | 上方向スワイプ |

### 本文テンプレート

```
タイトル: "Success" (StringConstants.success.localized())
サブタイトル: {removeAllCartProductModel.message} - サーバーからの成功メッセージ
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| message | 全削除成功メッセージ | BaseModel.message | Yes（空文字許容） |
| context | ビルドコンテキスト | Flutter Widget | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 全カート商品削除 | RemoveAllCartItemState.status == CartStatus.success | cart_screen.dart 行74-81 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 削除失敗 | RemoveAllCartItemState.status == CartStatus.fail の場合はエラー通知 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[全削除ボタンタップ] --> B[RemoveAllCartItemEvent発行]
    B --> C[CartScreenBloc処理]
    C --> D[repository.removeAllCartItem呼び出し]
    D --> E{API結果}
    E -->|成功| F[RemoveAllCartItemState.success emit]
    E -->|失敗| G[RemoveAllCartItemState.fail emit]
    F --> H[BlocConsumer listener検出]
    H --> I[ShowMessage.successNotification呼び出し]
    I --> J[緑色オーバーレイ表示]
    J --> K[カート数を0に更新]
    K --> L[カート画面リフレッシュ]
    G --> M[ShowMessage.errorNotification呼び出し]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| cart_items（サーバー側） | 削除対象全商品の確認 | API経由 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| cart_items（サーバー側） | DELETE ALL | カート内全商品の削除 |
| ローカルストレージ | UPDATE | カート商品数を0に更新 |

#### 送信後の状態更新

| 操作 | 項目 | 更新値 | 備考 |
|-----|-----|-------|------|
| sink.add | GlobalData.cartCountController | 0 | 行80 |
| setCartCount | appStoragePref | 更新後の itemsCount | 行185 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 全削除失敗 | API エラー | errorNotification表示（行75-76） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

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

- 全削除操作は認証済みユーザーのみ実行可能
- 他ユーザーのカートは削除不可（サーバー側で検証）
- 確認ダイアログを経由して実行されるべき（誤操作防止）

## 備考

- 全削除成功後、カート数は明示的に0に設定（`sink.add(0)`）
- 削除成功後、自動的にカートデータを再取得（`fetchCartData()`）
- 全削除は個別削除と異なり、一括でカートをクリア

---

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

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

### 推奨読解順序

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

全カート商品削除のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cart_screen_state.dart | `lib/screens/cart_screen/bloc/cart_screen_state.dart` | RemoveAllCartItemStateの構造 |

**読解のコツ**: `RemoveCartItemState`（個別削除）との違いに注目。全削除では`BaseModel`を使用。

#### Step 2: イベント発行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cart_screen_event.dart | `lib/screens/cart_screen/bloc/cart_screen_event.dart` | RemoveAllCartItemEventの定義 |

**主要処理フロー**:
- **行43-45**: `RemoveAllCartItemEvent` クラス
- 引数なし（全商品を対象とするため）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cart_screen_bloc.dart | `lib/screens/cart_screen/bloc/cart_screen_bloc.dart` | RemoveAllCartItemEvent処理 |

**主要処理フロー**:
- **行48-56**: `RemoveAllCartItemEvent` のハンドリング
- **行50-51**: `repository?.removeAllCartItem()` 呼び出し（引数なし）
- **行52-53**: 成功時 `RemoveAllCartItemState.success` emit
- **行54-56**: 失敗時 `RemoveAllCartItemState.fail` emit

#### Step 4: 通知表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cart_screen.dart | `lib/screens/cart_screen/cart_screen.dart` | listenerでの通知処理 |

**主要処理フロー**:
- **行74-81**: `RemoveAllCartItemState` の処理
- **行75-76**: 失敗時 `ShowMessage.errorNotification(state.error ?? "", context)`
- **行77-79**: 成功時 `ShowMessage.successNotification(state.removeAllCartProductModel!.message ?? "", context)`
- **行80**: カート数を0に更新 `GlobalData.cartCountController.sink.add(0)`

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

```
CartScreen（カート画面）
    |
    +-- 全削除ボタンタップ
            |
            +-- cartScreenBloc.add(RemoveAllCartItemEvent())
                    |
                    +-- CartScreenBloc.mapEventToState()
                            |
                            +-- repository.removeAllCartItem()
                                    |
                                    +-- API呼び出し（GraphQL Mutation）
                                            |
                                            +-- emit(RemoveAllCartItemState.success/fail)
                                                    |
                                                    +-- BlocConsumer.listener
                                                            |
                                                            +-- ShowMessage.successNotification()
                                                            |
                                                            +-- GlobalData.cartCountController.sink.add(0)
```

### データフロー図

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

全削除ボタンタップ ──────▶ RemoveAllCartItemEvent()
                                    |
                                    ▼
                            CartScreenBloc
                                    |
                                    ▼
                            repository.removeAllCartItem()
                                    |
                                    ▼
                            GraphQL API呼び出し
                                    |
                               ┌────┴────┐
                               ▼         ▼
                            成功       失敗
                               |         |
                               ▼         ▼
                  RemoveAllCartItemState  RemoveAllCartItemState
                        .success         .fail
                               |         |
                               ▼         ▼
                    successNotification  errorNotification
                               |
                               ▼
                    GlobalData.cartCountController.sink.add(0)
                               |
                               ▼
                    カート画面が空状態を表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cart_screen.dart | `lib/screens/cart_screen/cart_screen.dart` | ソース | カート画面UI・通知表示トリガー |
| cart_screen_bloc.dart | `lib/screens/cart_screen/bloc/cart_screen_bloc.dart` | ソース | カート操作のビジネスロジック |
| cart_screen_event.dart | `lib/screens/cart_screen/bloc/cart_screen_event.dart` | ソース | カート操作イベント定義 |
| cart_screen_state.dart | `lib/screens/cart_screen/bloc/cart_screen_state.dart` | ソース | カート操作状態定義 |
| cart_screen_repository.dart | `lib/screens/cart_screen/bloc/cart_screen_repository.dart` | ソース | カートAPI呼び出し |
| show_message.dart | `lib/widgets/show_message.dart` | ソース | 成功通知表示 |
| button_view.dart | `lib/screens/cart_screen/widget/button_view.dart` | ソース | 全削除ボタンUI |
