# 画面設計書 3-サインアップ画面

## 概要

本ドキュメントは、Chatwootアプリケーションのサインアップ画面に関する設計書です。新規ユーザーがアカウントを作成するための登録機能を提供する画面について記述しています。

### 本画面の処理概要

サインアップ画面は、新規ユーザーがChatwootアカウントを作成するための画面です。ビジネスメールアドレスとパスワードを入力し、アカウントを作成します。

**業務上の目的・背景**：Chatwootをセルフサービスで利用開始できるようにするため、ユーザー自身でアカウントを作成できる機能が必要です。本画面は、潜在的なユーザーが簡単にサービスを試用・導入できるエントリーポイントとして機能します。ビジネスメールアドレスのみを受け付けることで、個人利用ではなく企業利用を促進し、サービスの品質維持を図っています。また、hCaptchaによるボット対策や、パスワード強度要件の表示により、セキュリティを確保しています。

**画面へのアクセス方法**：ブラウザで `/app/auth/signup` にアクセスするか、ログイン画面から「新規アカウント作成」リンクをクリックして遷移します。サインアップ機能が無効な環境ではアクセスできません。

**主要な操作・処理内容**：
1. ビジネスメールアドレスを入力する
2. パスワードを入力する（パスワード要件がリアルタイム表示される）
3. hCaptcha認証を完了する（設定されている場合）
4. サインアップボタンを押下してアカウントを作成する
5. Google OAuthボタンをクリックしてGoogleアカウントでサインアップする
6. ログインリンクをクリックして既存アカウントでログインする

**画面遷移**：
- 遷移元：ログイン画面（サインアップリンク）、直接URL入力
- 遷移先：ダッシュボードホーム画面（登録成功後）、ログイン画面（既存アカウントリンク）

**権限による表示制御**：
- サインアップ機能が有効な環境でのみアクセス可能（`requireSignupEnabled`メタ情報）
- Google OAuthボタン：`allowedLoginMethods`に`google_oauth`が含まれ、`googleOAuthClientId`が設定されている場合のみ表示
- テスティモニアルセクション：Chatwoot公式インスタンスの場合のみ表示
- hCaptcha：`hCaptchaSiteKey`が設定されている場合のみ実行

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | アカウント作成・管理 | 主機能 | 新規ユーザー登録とアカウント作成 |
| 1 | ユーザー認証 | 補助機能 | 登録後の自動ログイン処理 |

## 画面種別

登録（サインアップ）

## URL/ルーティング

| パス | ルート名 | 説明 |
|------|----------|------|
| `/app/auth/signup` | `auth_signup` | サインアップ画面 |

### ルートメタ情報

| メタキー | 値 | 説明 |
|---------|-----|------|
| `requireSignupEnabled` | `true` | サインアップ機能有効時のみアクセス可能 |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | バリデーション | 説明 |
|--------|--------|-----|------|----------------|------|
| メールアドレス | `email` | email | Yes | required, email形式, ビジネスメールのみ | 登録用ビジネスメールアドレス |
| パスワード | `password` | password | Yes | required, 6文字以上, パスワード強度要件 | 登録用パスワード |

### パスワード強度要件

- 最低6文字以上
- 英大文字を含む
- 英小文字を含む
- 数字を含む
- 特殊文字を含む

### 出力項目

登録成功時はダッシュボードにリダイレクトされるため、本画面での出力項目はありません。

## 表示項目

| 項目名 | 説明 | 表示条件 |
|--------|------|----------|
| ロゴ | アプリケーションロゴ（ライト/ダークモード対応） | 常時 |
| タイトル | 「始めましょう」または「Wootを試す」 | Chatwootインスタンスか否かで切り替え |
| ログインリンク | 既存アカウントでログインへのリンク | 常時 |
| メールアドレス入力欄 | ビジネスメールアドレス入力 | 常時 |
| パスワード入力欄 | パスワード入力 | 常時 |
| パスワード要件表示 | パスワード強度要件のリアルタイム表示 | パスワード入力欄にフォーカス時 |
| サインアップボタン | 登録実行ボタン | 常時 |
| Google OAuthボタン | Googleでサインアップボタン | Google OAuth設定済みの場合 |
| 利用規約リンク | 利用規約とプライバシーポリシーへのリンク | 常時 |
| テスティモニアルセクション | 顧客の声（デスクトップ表示） | Chatwootインスタンスの場合 |
| ローディングスピナー | テスティモニアル読み込み中 | Chatwootインスタンスで読み込み中 |

## イベント仕様

### 1-サインアップボタン押下

**トリガー**: サインアップボタンのクリックまたはフォーム送信

**処理フロー**:
1. 処理中の場合は何もしない
2. フロントエンドでバリデーション実行
   - メールアドレス形式チェック
   - ビジネスメールチェック（個人メールドメインを除外）
   - パスワード強度チェック
3. バリデーションエラー時は処理を中断
4. hCaptcha設定がある場合はhCaptcha実行
5. hCaptcha完了後または未設定時は `performRegistration` を実行
6. API `POST /api/v1/accounts.json` にユーザー情報を送信
7. レスポンスに応じた処理:
   - 登録成功: 認証情報を保存し、ダッシュボードにリダイレクト
   - 登録失敗: エラーメッセージ表示、hCaptchaリセット

**データフロー**:
```
[ユーザー入力]
    │
    ▼
[バリデーション] ──エラー──▶ [処理中断]
    │
    │ 成功
    ▼
[hCaptcha設定確認]
    │
    ├─ 設定あり ─▶ [hCaptcha実行]
    │                    │
    │                    ▼
    │              [トークン取得]
    │                    │
    └─ 設定なし ─────────┘
                         │
                         ▼
                [register API呼び出し]
                         │
                    ┌────┴────┐
                    ▼         ▼
                [成功]     [失敗]
                  │          │
                  ▼          ▼
            認証情報保存   エラー表示
            リダイレクト   hCaptchaリセット
```

### 2-Google OAuthボタン押下

**トリガー**: Google OAuthボタンのクリック

**処理フロー**:
1. Googleの認証ページにリダイレクト
2. Google側で認証処理
3. コールバックURLに認証結果とともにリダイレクト
4. 認証成功時: アカウント作成または既存アカウントでログイン、ダッシュボードにリダイレクト
5. 認証失敗時: エラーパラメータ付きでログイン画面に戻る

### 3-ログインリンク押下

**トリガー**: 「既にアカウントをお持ちですか？」リンクのクリック

**処理フロー**:
1. `/app/login` にルーター遷移
2. ログイン画面を表示

### 4-パスワード入力欄フォーカス

**トリガー**: パスワード入力欄へのフォーカス

**処理フロー**:
1. `isPasswordFocused` を `true` に設定
2. パスワード要件コンポーネントをアニメーション表示
3. 入力中のパスワードに対してリアルタイムで要件充足状況を表示

### 5-パスワード入力欄ブラー

**トリガー**: パスワード入力欄からのフォーカス離脱

**処理フロー**:
1. `isPasswordFocused` を `false` に設定
2. パスワード要件コンポーネントをアニメーション非表示
3. バリデーションを実行

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| サインアップ成功 | accounts | INSERT | 新規アカウントレコード作成 |
| サインアップ成功 | users | INSERT | 新規ユーザーレコード作成 |
| サインアップ成功 | account_users | INSERT | アカウントとユーザーの関連付け |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | メールドメインから生成 | アカウント名 |
| INSERT | created_at | 現在時刻 | 作成日時 |
| INSERT | updated_at | 現在時刻 | 更新日時 |

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | email | 入力メールアドレス | ユーザーメール |
| INSERT | name | メールアドレスから生成 | ユーザー名 |
| INSERT | encrypted_password | パスワードをハッシュ化 | 暗号化パスワード |
| INSERT | created_at | 現在時刻 | 作成日時 |
| INSERT | updated_at | 現在時刻 | 更新日時 |

#### account_users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | account_id | 作成したアカウントID | アカウント参照 |
| INSERT | user_id | 作成したユーザーID | ユーザー参照 |
| INSERT | role | 'administrator' | 初期ロール |
| INSERT | created_at | 現在時刻 | 作成日時 |

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|---------------|---------------|----------|
| REGISTER.API.ERROR_MESSAGE | エラー | 登録に失敗しました | 登録失敗時 |
| REGISTER.EMAIL.ERROR | エラー | ビジネスメールアドレスを入力してください | メールバリデーションエラー時 |

## 例外処理

| 例外条件 | 状態・動作 |
|---------|----------|
| サインアップ機能無効 | ルートガードによりアクセス拒否 |
| メールアドレス重複 | エラーメッセージを表示 |
| 個人メールアドレス使用 | バリデーションエラー（ビジネスメールのみ） |
| パスワード強度不足 | バリデーションエラー、要件不足を表示 |
| hCaptcha検証失敗 | エラー表示、hCaptchaリセット |
| hCaptchaタイムアウト | エラー表示、hCaptchaリセット |
| ネットワークエラー | エラーメッセージを表示 |
| サーバーエラー（500系） | エラーメッセージを表示 |

## 備考

- ビジネスメールバリデーションには `company-email-validator` ライブラリを使用
- パスワード要件コンポーネント（PasswordRequirements）がリアルタイムで要件充足状況を表示
- テスティモニアルセクションはChatwoot公式インスタンス（`installationName === 'Chatwoot'`）でのみ表示
- hCaptchaは `invisible` モードで実行され、ユーザー操作は最小限
- ダークモードに対応しており、システム設定に応じてロゴ画像が切り替わる
- 登録成功後は自動的にログイン状態となり、ダッシュボードにリダイレクト

---

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

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

### 推奨読解順序

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

登録処理で扱われるデータ構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | auth.js | `app/javascript/v3/api/auth.js` | register関数のリクエスト/レスポンス形式 |

**読解のコツ**: `register`関数（行50-66）で、メールアドレスからアカウント名とユーザー名を自動生成している点に注目してください。

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

処理の起点となるVueコンポーネントを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue | `app/javascript/v3/views/auth/signup/Index.vue` | サインアップ画面のメインコンポーネント |
| 2-2 | Form.vue | `app/javascript/v3/views/auth/signup/components/Signup/Form.vue` | サインアップフォームコンポーネント |
| 2-3 | routes.js | `app/javascript/v3/views/routes.js` | ルーティング定義、`requireSignupEnabled`メタ情報 |

**主要処理フロー**:
1. **Form.vue 行92-102**: `submit`メソッドでバリデーションとhCaptcha処理
2. **Form.vue 行75-90**: `performRegistration`メソッドでAPI呼び出し
3. **Form.vue 行33-48**: バリデーションルール定義

#### Step 3: サブコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PasswordRequirements.vue | `app/javascript/v3/views/auth/signup/components/Signup/PasswordRequirements.vue` | パスワード要件表示 |
| 3-2 | Testimonials/Index.vue | `app/javascript/v3/views/auth/signup/components/Testimonials/Index.vue` | テスティモニアル表示 |

#### Step 4: 登録API層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | auth.js | `app/javascript/v3/api/auth.js` | register関数の実装（行50-66） |
| 4-2 | AuthHelper.js | `app/javascript/v3/helpers/AuthHelper.js` | `getCredentialsFromEmail`によるアカウント名生成 |

**主要処理フロー**:
- **auth.js 行52**: メールアドレスからアカウント名とユーザー名を生成
- **auth.js 行53-59**: `POST /api/v1/accounts.json` エンドポイントへのリクエスト
- **auth.js 行60**: 認証情報の保存

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

```
Index.vue (サインアップ画面)
    │
    └─ SignupForm (Form.vue)
           │
           ├─ submit()
           │      │
           │      ├─ v$.value.$touch() [バリデーション]
           │      │
           │      ├─ [hCaptcha設定あり]
           │      │      │
           │      │      └─ hCaptcha.value.execute()
           │      │             │
           │      │             └─ onRecaptchaVerified()
           │      │                    │
           │      │                    └─ performRegistration()
           │      │
           │      └─ [hCaptcha設定なし]
           │             │
           │             └─ performRegistration()
           │                    │
           │                    └─ register() [auth.js]
           │                           │
           │                           ├─ getCredentialsFromEmail()
           │                           │
           │                           ├─ wootAPI.post('/api/v1/accounts.json')
           │                           │      │
           │                           │      └─ [Backend] accounts_controller#create
           │                           │
           │                           └─ setAuthCredentials() → redirect
           │
           ├─ PasswordRequirements
           │      └─ パスワード要件リアルタイム表示
           │
           └─ GoogleOAuthButton
                  └─ Google OAuth認証フロー
```

### データフロー図

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

credentials.email    ──▶   Form.vue                     ──▶   ダッシュボード
credentials.password       (submit)                            リダイレクト
hCaptchaResponse              │
                              ▼
                          [バリデーション]
                              │
                              ▼
                          [hCaptcha実行（条件付き）]
                              │
                              ▼
                          register() [auth.js]
                              │
                              ▼
                          getCredentialsFromEmail()
                              │
                              ▼
                          POST /api/v1/accounts.json
                          {
                            account_name,
                            user_full_name,
                            email,
                            password,
                            h_captcha_client_response
                          }
                              │
                              ▼
                          [Backend]
                          accounts_controller#create
                              │
                     ┌────────┴────────┐
                     ▼                 ▼
                [成功]             [失敗]
                  │                  │
                  ▼                  ▼
            認証情報保存         エラー表示
            localStorage         hCaptchaリセット
                  │
                  ▼
            ダッシュボード
            リダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/v3/views/auth/signup/Index.vue` | ソース | サインアップ画面メインコンポーネント |
| Form.vue | `app/javascript/v3/views/auth/signup/components/Signup/Form.vue` | ソース | サインアップフォームコンポーネント |
| PasswordRequirements.vue | `app/javascript/v3/views/auth/signup/components/Signup/PasswordRequirements.vue` | ソース | パスワード要件表示コンポーネント |
| Testimonials/Index.vue | `app/javascript/v3/views/auth/signup/components/Testimonials/Index.vue` | ソース | テスティモニアル表示コンポーネント |
| routes.js | `app/javascript/v3/views/routes.js` | ソース | ルーティング定義 |
| auth.js | `app/javascript/v3/api/auth.js` | ソース | 認証API関数 |
| AuthHelper.js | `app/javascript/v3/helpers/AuthHelper.js` | ソース | 認証ヘルパー関数 |
| FormInput.vue | `app/javascript/v3/components/Form/Input.vue` | ソース | 入力フォームコンポーネント |
| GoogleOAuthButton.vue | `app/javascript/v3/components/GoogleOauth/Button.vue` | ソース | Google OAuth ボタン |
| Validators.js | `app/javascript/shared/helpers/Validators.js` | ソース | パスワードバリデーション |
| en.json | `app/javascript/dashboard/i18n/locale/en/register.json` | 設定 | i18n翻訳ファイル |
