# 画面設計書 45-ユーザー参加画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるユーザー参加画面の設計仕様を定義したものです。参加コードを使用してアカウントに参加した新規ユーザーが、自身の名前を設定するための画面について記載しています。

### 本画面の処理概要

本画面は、新規ユーザーがアカウントに参加した後、自身の表示名を設定するための画面です。ユーザー検証画面（No.46）での検証が完了した後に遷移し、名前を入力して登録を完了します。

**業務上の目的・背景**：Fizzyでは参加コードを使用して新規ユーザーをアカウントに招待できます。招待されたユーザーは、メールアドレスでの認証（マジックリンク）の後、自身の名前を設定する必要があります。本画面はこのオンボーディングフローの最終ステップとして機能し、ユーザーが他のメンバーに認識される名前を設定できるようにします。

**画面へのアクセス方法**：ユーザー検証画面（No.46）での検証完了後に自動的に遷移します。また、参加コードによるサインアップフローの一部として表示されます。

**主要な操作・処理内容**：
1. フルネーム（表示名）を入力する
2. 「Continue」ボタンをクリックして名前を登録する
3. ランディングページ（ホーム画面）にリダイレクトされる

**画面遷移**：
- 遷移元：ユーザー検証画面（No.46）
- 遷移先：ランディングページ（landing_path）→ アクティビティ一覧画面（No.8）

**権限による表示制御**：本画面は認証済みユーザーのみアクセス可能です。通常、新規参加ユーザーのオンボーディングフローでのみ表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | 参加コードによるアカウント参加 | 主機能 | 新規ユーザーが参加する処理 |

## 画面種別

登録（フォーム入力）

## URL/ルーティング

- パス: `/users/joins/new`
- HTTPメソッド: GET（表示）/ POST（登録）
- ルート名: `new_users_join_path` / `users_joins_path`
- コントローラ: `Users::JoinsController#new` / `#create`
- レイアウト: `public`

## 入出力項目

| 項目名 | 項目ID | 種別 | 必須 | 形式 | 最大長 | 説明 |
|--------|--------|------|------|------|--------|------|
| 名前 | user[name] | 入力 | ○ | text | - | ユーザーの表示名（フルネーム） |
| アバター | user[avatar] | 入力 | - | file | - | プロフィール画像（オプション） |

## 表示項目

| 項目名 | 説明 | 表示条件 |
|--------|------|----------|
| ページタイトル | "Great! Now enter your name" | 常時 |
| 名前入力フィールド | フルネーム入力用 | 常時 |
| 送信ボタン | "Continue" | 常時 |
| フッター | セッション関連のフッター | 常時 |

## イベント仕様

### 1-Continueボタン押下

フォームが送信され、以下の処理が実行されます：
1. POSTリクエストが`users_joins_path`に送信される
2. Current.userの名前（とオプションでアバター）が更新される
3. ランディングページ（`landing_path`）にリダイレクトされる

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Continueボタン押下 | users | UPDATE | ユーザーの名前を更新 |
| Continueボタン押下（アバター指定時） | active_storage_attachments | INSERT | アバター画像を添付 |
| Continueボタン押下（アバター指定時） | active_storage_blobs | INSERT | アバター画像のBlobを作成 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォームで入力された名前 | 必須 |
| UPDATE | updated_at | 現在時刻 | - |

#### active_storage_attachments（アバター指定時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | "avatar" | - |
| INSERT | record_type | "User" | - |
| INSERT | record_id | Current.user.id | - |
| INSERT | blob_id | 新規作成されたBlobのID | - |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | プレースホルダ | Full name | 名前入力フィールドに表示 |

## 例外処理

| 例外ケース | 対応 |
|-----------|------|
| 認証されていない | ログイン画面へリダイレクト |
| 名前が空 | バリデーションエラー（HTMLのrequired属性） |
| 名前の更新に失敗 | 例外発生（update!使用） |

## 備考

- レイアウトは「public」が使用される
- フォームにはStimulusコントローラ（`form`）が適用されている
- 名前入力フィールドには`autofocus`が設定されている
- `1p-ignore`データ属性により、1Passwordによる自動入力が無効化されている
- フッターには`sessions/footer`パーシャルが表示される
- アバターはStrongParametersで許可されているが、UIには表示されていない（拡張用）

---

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

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

### 推奨読解順序

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

名前設定に関わるモデルの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | Userモデルのname属性とバリデーションを確認 |
| 1-2 | avatar.rb | `app/models/user/avatar.rb` | アバター添付の仕組みを確認（存在する場合） |

**読解のコツ**: `validates :name, presence: true`により名前は必須であることを確認してください。

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

処理の起点となるコントローラを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | joins_controller.rb | `app/controllers/users/joins_controller.rb` | newとcreateアクションの実装を確認 |

**主要処理フロー**:
1. **行2**: `layout "public"` - publicレイアウトの使用
2. **行4-5**: `new`アクション - ビューをレンダリング
3. **行7-9**: `create`アクション - ユーザー情報を更新しリダイレクト
4. **行8**: `Current.user.update!(user_params)` - 名前とアバターを更新
5. **行9**: `redirect_to landing_path` - ランディングページへリダイレクト

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.erb | `app/views/users/joins/new.html.erb` | フォーム構造とStimulusコントローラの適用を確認 |

**主要処理フロー**:
- **行1**: ページタイトルの設定
- **行6**: フォームのスコープ設定（"user"）とPOST先（users_joins_path）
- **行9**: 名前入力フィールド（テキスト、必須、autofocus）
- **行20-22**: フッターの表示

#### Step 4: ルーティングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | routes.rb | `config/routes.rb` | users/joinsのルーティングを確認 |

**主要処理フロー**:
- **行149-152**: `namespace :users do resources :joins end`

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

```
Users::JoinsController#new
    │
    └─ new.html.erb レンダリング

Users::JoinsController#create
    │
    ├─ user_params
    │      └─ params.expect(user: [:name, :avatar])
    │
    ├─ Current.user.update!(user_params)
    │      │
    │      ├─ name属性の更新
    │      │
    │      └─ avatar属性の更新（指定時）
    │
    └─ redirect_to landing_path
```

### データフロー図

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

名前（必須）           JoinsController#create
user[name] ───────▶         │
                            ├─▶ Current.user.update!
アバター（任意）            │      │
user[avatar] ─────▶         │      └─▶ users テーブル更新
                            │
                            └─▶ redirect_to landing_path ───▶ アクティビティ
                                                               一覧画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| joins_controller.rb | `app/controllers/users/joins_controller.rb` | コントローラ | 画面制御・ユーザー更新 |
| new.html.erb | `app/views/users/joins/new.html.erb` | ビュー | 名前入力フォームの表示 |
| user.rb | `app/models/user.rb` | モデル | ユーザーエンティティ |
| _footer.html.erb | `app/views/sessions/_footer.html.erb` | パーシャル | フッター表示 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（行149-152） |
