# 画面設計書 25-企業一覧画面

## 概要

本ドキュメントは、Chatwootの企業一覧画面の設計仕様を記述したものである。

### 本画面の処理概要

企業一覧画面は、登録された企業（Company）の一覧を表示し、管理する機能を提供する画面である。

**業務上の目的・背景**：B2B向けの顧客サポートにおいて、連絡先を企業単位で管理することは重要である。本画面により、オペレーターは企業情報の一覧表示、検索、ソートを行い、企業に所属する連絡先を効率的に管理することができる。これにより、企業単位での問い合わせ傾向の把握や、担当者との関係構築が容易になる。

**画面へのアクセス方法**：ダッシュボードのサイドバーから「企業」メニューをクリックすることでアクセスする。URLは `/app/accounts/:accountId/companies` の形式となる。

**主要な操作・処理内容**：
1. 企業一覧の表示
2. 企業の検索（名前、ドメインなど）
3. ソート順の変更（名前、更新日時など）
4. ページネーションによる一覧のページ切り替え
5. 企業詳細への遷移

**画面遷移**：ダッシュボードホームから遷移可能。各企業をクリックすると企業詳細画面に遷移する。

**権限による表示制御**：Cloud版またはEnterprise版のみ利用可能。CRM機能フラグが有効である必要がある。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 66 | 連絡先所属企業 | 主機能 | 企業の一覧表示と管理 |

## 画面種別

一覧

## URL/ルーティング

| パス | ルート名 | 説明 |
|------|----------|------|
| `/app/accounts/:accountId/companies` | companies_index | 企業一覧画面 |

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| page | クエリパラメータ | 任意 | ページ番号（デフォルト: 1） |
| search | クエリパラメータ | 任意 | 検索キーワード |
| sort | クエリパラメータ | 任意 | ソート条件 |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| companies | Array | 企業オブジェクトの配列 |
| meta | Object | ページネーション情報（totalCount） |

## 表示項目

### ヘッダー情報

| 項目名 | 説明 |
|--------|------|
| タイトル | 「企業」（i18nキー: COMPANIES.HEADER） |
| 総件数 | 企業の総数 |

### 企業カード一覧

| 項目名 | 説明 | データソース |
|--------|------|--------------|
| 企業名 | 企業の名称 | company.name |
| ドメイン | 企業のドメイン | company.domain |
| 説明 | 企業の説明 | company.description |
| アバター | 企業のロゴ/アイコン | company.avatarUrl |
| 連絡先数 | 所属する連絡先の数 | company.contactsCount |
| 更新日時 | 最終更新日時 | company.updatedAt |

## イベント仕様

### 1-画面初期表示

画面マウント時、企業一覧を取得する。

**処理フロー**:
1. URLパラメータから検索条件、ページ番号を取得
2. `companiesStore.get` または `companiesStore.search` を実行
3. 結果をストアに保存し、画面に表示

### 2-検索実行

検索ボックスに入力後、デバウンス処理（300ms）を経て検索APIを呼び出す。

**処理フロー**:
1. 入力値をデバウンス処理
2. `companiesStore.search` を実行
3. URLのクエリパラメータに検索条件を反映
4. 検索結果を画面に表示

### 3-ソート変更

ソートメニューから並び順を選択すると、指定条件で再取得を実行する。

**処理フロー**:
1. ソート条件を`sortState`に保存
2. `updateUISettings`でソート設定を永続化
3. `fetchCompanies`を実行
4. 再取得した結果を表示

### 4-ページ変更

ページネーションコントロールでページを切り替える。

**処理フロー**:
1. `onPageChange`を新しいページ番号で実行
2. URLのpageパラメータを更新
3. `fetchCompanies`で新しいページのデータを取得

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面初期表示 | companies | SELECT | 企業一覧取得 |
| 検索実行 | companies | SELECT | 検索条件で企業を検索 |

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

#### companies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | ページネーション、ソート条件適用 | 一覧取得 |
| SELECT | * | 検索条件に合致 | 検索時 |

## メッセージ仕様

| 種別 | コード | メッセージ | 表示条件 |
|------|--------|-----------|----------|
| 情報 | COMPANIES.LOADING | 読み込み中... | データ取得中 |
| 情報 | COMPANIES.EMPTY_STATE.TITLE | 企業がありません | 企業が0件の場合 |

## 例外処理

| 例外条件 | 処理内容 |
|----------|---------|
| 企業が0件 | 空状態メッセージを表示 |
| API通信エラー | ローディング状態を解除し、エラーアラートを表示 |
| 権限不足 | 画面へのアクセスがブロック |
| フィーチャーフラグ無効 | 画面へのアクセス不可 |

## 備考

- Cloud版またはEnterprise版限定機能
- Piniaストア（useCompaniesStore）を使用
- ソート設定はUI設定として永続化（companies_sort_by）
- デフォルトソートは名前順（name）
- 企業カードはCompaniesCardコンポーネントで表示

---

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

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

### 推奨読解順序

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

まず、企業のデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | companies.js | `app/javascript/dashboard/stores/companies.js` | Piniaストアの構造、getters、actions |

**読解のコツ**: Piniaストアの`state`とカスタム`getters`を見ることで、どのようなデータが管理されているか把握できる。

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

処理の起点となるVueコンポーネントを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CompaniesIndex.vue | `app/javascript/dashboard/routes/dashboard/companies/pages/CompaniesIndex.vue` | 画面のメインコンポーネント |

**主要処理フロー**:
1. **行15**: `useCompaniesStore()`でストアを取得
2. **行23-25**: `companies`, `meta`, `uiFlags`をcomputedで取得
3. **行81-103**: `fetchCompanies`で企業一覧取得
4. **行105-108**: `onSearch`でデバウンス検索
5. **行114-122**: `handleSort`でソート処理
6. **行124-127**: `onMounted`で初期データ取得

#### Step 3: Piniaストアを理解する

企業データ管理のビジネスロジックを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | companies.js | `app/javascript/dashboard/stores/companies.js` | get, searchアクション |

**主要処理フロー**:
- **行11-13**: `getCompaniesList` getterでcamelCase変換
- **行16-29**: `search`アクションで検索処理

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

バックエンドとの通信処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | companies.js | `app/javascript/dashboard/api/companies.js` | get, searchメソッド |

**主要処理フロー**:
- **行25-29**: `get`メソッドでGETリクエスト
- **行31-34**: `search`メソッドで検索リクエスト

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

```
CompaniesIndex.vue (View層)
    │
    ├─ onMounted
    │      │
    │      └─ fetchCompanies
    │             ├─ companiesStore.get() (検索なし)
    │             │      └─ CompanyAPI.get()
    │             │             └─ axios.get('/companies')
    │             │
    │             └─ companiesStore.search() (検索あり)
    │                    └─ CompanyAPI.search()
    │                           └─ axios.get('/companies/search')
    │
    ├─ onSearch (検索時)
    │      └─ fetchCompanies (with search param)
    │
    ├─ onPageChange (ページ変更時)
    │      └─ fetchCompanies (with page param)
    │
    └─ handleSort (ソート変更時)
           └─ fetchCompanies (with sort param)
```

### データフロー図

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

URLパラメータ ──────────▶ fetchCompanies
(page, search, sort)            │
                                ▼
                         CompanyAPI.get/search()
                                │
                                ▼
                         Rails API (/api/v1/accounts/:account_id/companies)
                                │
                                ▼
                         Piniaストア更新 ───▶ 画面表示更新
                                                    │
                                                    └─ CompaniesCard表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CompaniesIndex.vue | `app/javascript/dashboard/routes/dashboard/companies/pages/CompaniesIndex.vue` | ソース | メイン画面コンポーネント |
| companies.js (store) | `app/javascript/dashboard/stores/companies.js` | ソース | Piniaストア |
| companies.js (api) | `app/javascript/dashboard/api/companies.js` | ソース | 企業API |
| CompaniesListLayout.vue | `app/javascript/dashboard/components-next/Companies/CompaniesListLayout.vue` | ソース | リストレイアウトコンポーネント |
| CompaniesCard.vue | `app/javascript/dashboard/components-next/Companies/CompaniesCard/CompaniesCard.vue` | ソース | 企業カードコンポーネント |
| storeFactory.js | `app/javascript/dashboard/store/storeFactory.js` | ソース | ストアファクトリー |
| useUISettings.js | `app/javascript/dashboard/composables/useUISettings.js` | ソース | UI設定composable |
