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

## 概要

本ドキュメントは、Giselle Studio のメールサインアップ画面の設計仕様を記載したものである。

### 本画面の処理概要

メールサインアップ画面は、新規ユーザーがメールアドレスとパスワードを使用してGiselle Studioにアカウントを作成するための登録フォームである。OAuth認証を使用しないユーザーに対して、メール/パスワードベースの認証手段を提供する。

**業務上の目的・背景**：本画面は、OAuthプロバイダー（GitHub、Google）を使用したくないユーザー、または企業ポリシーによりOAuth認証が制限されているユーザーに対して、代替の登録手段を提供する。メールアドレスによる登録は、ユーザーの匿名性を保ちつつ、アカウント認証を実現する。パスワードバリデーションにより、セキュアなアカウント作成を促進する。

**画面へのアクセス方法**：以下の方法でメールサインアップ画面にアクセスできる。
- サインアップ画面から「Sign up with Email」ボタンをクリック
- ブラウザで直接 `/signup/email` URLにアクセス

**主要な操作・処理内容**：
1. メールアドレス入力：有効なメールアドレスを入力
2. パスワード入力：6文字以上のパスワードを入力
3. サインアップ実行：「Sign up」ボタンを押下してアカウント作成を開始
4. 他の登録方法への遷移：「other way?」リンクからサインアップ画面へ戻る

**画面遷移**：
- 遷移元：サインアップ画面
- 遷移先：メール確認画面（認証成功時）、サインアップ画面（他の方法選択時）

**権限による表示制御**：メールサインアップ画面は未認証ユーザーのみがアクセス可能である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 96 | ユーザー認証 | 主機能 | メールアドレスとパスワードによる新規ユーザー登録処理 |

## 画面種別

認証（登録フォーム）

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| URL | `/signup/email` |
| ルートファイル | `apps/studio.giselles.ai/app/(auth)/signup/email/page.tsx` |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | 最大長 | 説明 |
|--------|--------|-----|------|--------|------|
| メールアドレス | email | string | Yes | 254 | 登録用メールアドレス |
| パスワード | password | string | Yes | - | 6文字以上のパスワード |

### 出力項目

本画面での直接的な出力項目はない。サインアップ成功時はメール確認画面へリダイレクト、失敗時はエラーメッセージを表示する。

## 表示項目

| 項目名 | 表示内容 | 説明 |
|--------|----------|------|
| ページタイトル | "Unleash Your Potential" | ヘッダー部のメインタイトル |
| サブタイトル | "New here? Launch your first agent and start building with Giselle." | タイトル下の説明文 |
| フォームタイトル | "Sign up with Email" | フォームコンテナのタイトル |
| メールラベル | "Email" | メール入力フィールドのラベル |
| パスワードラベル | "Password" | パスワード入力フィールドのラベル |
| サインアップボタン | "Sign up" | サインアップ実行ボタン |
| 利用規約同意 | LegalConsent コンポーネント | 利用規約への同意表示 |
| 他の方法誘導 | "Get started by " + "other way?" | サインアップ画面への誘導 |

## イベント仕様

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

**トリガー**: "Sign up" ボタンをクリック

**処理フロー**:
1. フォームデータから `email`, `password` を取得
2. クライアントサイドでValibotスキーマによるバリデーション実行
3. バリデーションエラーがある場合、エラーメッセージを表示して処理中断
4. バリデーション成功時、`SignupContext`にメールアドレスを保存（`SET_EMAIL`アクション）
5. Server Action `signup` を呼び出し
6. Supabase Auth クライアントを作成
7. `signUp` メソッドでユーザー登録を実行
8. 登録成功時、`/signup/verify-email`（メール確認画面）にリダイレクト

**バリデーションルール**:
- メールアドレス：必須、1文字以上254文字以下、有効なメールアドレス形式
- パスワード：必須、6文字以上

**例外処理**:
- バリデーションエラー：フィールドごとにエラーメッセージを表示
- 登録失敗（メールアドレス重複など）：Supabaseからのエラーを`createAuthError`でラップして表示

### 2-他の方法リンク押下

**トリガー**: "other way?" リンクをクリック

**処理フロー**:
1. Next.js Link コンポーネントによるクライアントサイドナビゲーション
2. `/signup` ページ（サインアップ画面）に遷移

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| サインアップ実行 | - | - | Supabase Authでの仮登録のみ（メール確認後に本登録） |

※サインアップ時点ではSupabase Authにのみユーザーが仮登録される。Giselleアプリケーションのデータベースへの登録は、メール確認後の`verifyEmail`処理で`initializeAccount`が呼ばれた際に行われる。

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|--------------|---------------|----------|
| バリデーションエラー | "Email is required" | メールアドレスが未入力の場合 |
| バリデーションエラー | "Email address is too long" | メールアドレスが254文字を超える場合 |
| バリデーションエラー | "Email address is not valid" | メールアドレス形式が不正な場合 |
| バリデーションエラー | "Password is required" | パスワードが未入力の場合 |
| バリデーションエラー | "Password must be at least 6 characters" | パスワードが6文字未満の場合 |
| 認証エラー | Supabaseからのエラーメッセージ | 登録処理でエラーが発生した場合 |

## 例外処理

| 例外種別 | 条件 | 処理内容 |
|---------|------|----------|
| バリデーションエラー | 入力値がスキーマに適合しない | フィールド下にエラーメッセージを表示し、フォームを再表示 |
| メールアドレス重複 | 既に登録済みのメールアドレス | Supabaseエラーメッセージを表示 |
| ネットワークエラー | サーバー通信失敗 | サービス不可メッセージを表示 |

## 備考

- クライアントサイドバリデーションにはValibotを使用
- `SignupContext`でメールアドレスを保持し、メール確認画面で参照する
- `useActionState`フックで認証状態を管理
- フォームは`noValidate`属性を持ち、ブラウザのネイティブバリデーションを無効化

---

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

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

### 推奨読解順序

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

まず、バリデーションスキーマとコンテキストの型を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | validations.ts | `apps/studio.giselles.ai/app/(auth)/signup/email/validations.ts` | Valibotスキーマ定義（行3-14）、`ValidationErrors`型（行18-20） |
| 1-2 | types.ts | `apps/studio.giselles.ai/app/(auth)/signup/types.ts` | `SignupState`型の定義 |
| 1-3 | context.tsx | `apps/studio.giselles.ai/app/(auth)/signup/context.tsx` | `SignupContext`の定義と使用方法（行14-37） |

**読解のコツ**: Valibotの`v.pipe()`は複数のバリデーションルールをチェーンする。エラーメッセージは各バリデーターの第2引数で指定されている。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | page.tsx | `apps/studio.giselles.ai/app/(auth)/signup/email/page.tsx` | Server Componentとしてのページ構造（行9-37） |

**主要処理フロー**:
1. **行11-14**: `AuthContainer`でページレイアウトを構成
2. **行17-19**: `SignupForm`でフォームを表示
3. **行26-32**: サインアップ画面へのリンクを表示

#### Step 3: フォームコンポーネントを理解する

フォームの状態管理とバリデーション処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | signup-form.tsx | `apps/studio.giselles.ai/app/(auth)/signup/email/signup-form.tsx` | `useActionState`と`useState`の併用（行16-43）、バリデーション処理（行20-35） |

**主要処理フロー**:
- **行12**: `useSignupContext`でコンテキストを取得
- **行16-43**: `useActionState`でServer Actionをラップ、バリデーションとディスパッチを実行
- **行20-21**: `safeParse`でバリデーション実行
- **行23-35**: バリデーションエラー時の処理
- **行38**: バリデーション成功時に`SET_EMAIL`アクションをディスパッチ
- **行40**: Server Action `signup`を呼び出し

#### Step 4: Server Action（登録処理）を理解する

実際の登録ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | signup.ts | `apps/studio.giselles.ai/app/(auth)/signup/email/signup.ts` | サインアップのServer Action実装（行7-21） |

**主要処理フロー**:
- **行10**: Supabaseクライアント作成
- **行12**: `supabase.auth.signUp`でユーザー登録
- **行14-16**: エラーハンドリング
- **行18-19**: 成功時に`/signup/verify-email`へリダイレクト

#### Step 5: コンテキスト管理を理解する

メールアドレスの状態管理方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | reducer.ts | `apps/studio.giselles.ai/app/(auth)/signup/reducer.ts` | `signupReducer`の実装 |
| 5-2 | layout.tsx | `apps/studio.giselles.ai/app/(auth)/signup/layout.tsx` | `SignupContextProvider`のマウント位置 |

**主要処理フロー**:
- **context.tsx 行21**: `useReducer`で状態管理
- **reducer.ts**: `SET_EMAIL`アクションでメールアドレスを保存

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

```
layout.tsx
    │
    └─ SignupContextProvider
           │
           └─ page.tsx (Server Component)
                  │
                  ├─ AuthContainer (レイアウト)
                  │      └─ AuthContainerHeader
                  │
                  ├─ SignupForm (Client Component)
                  │      │
                  │      ├─ useSignupContext() ─▶ SignupContext
                  │      │
                  │      ├─ useActionState(wrappedSignup)
                  │      │      │
                  │      │      ├─ safeParse (Valibot)
                  │      │      │      └─ バリデーションエラー ─▶ setValidationError
                  │      │      │
                  │      │      ├─ dispatch({ type: "SET_EMAIL" })
                  │      │      │
                  │      │      └─ signup (Server Action)
                  │      │             └─ supabase.auth.signUp
                  │      │                    └─ redirect(/signup/verify-email)
                  │      │
                  │      └─ Form (共通フォームUI)
                  │
                  ├─ LegalConsent (利用規約同意)
                  │
                  └─ ActionPrompt (他の方法誘導)
                         └─ Link (/signup)
```

### データフロー図

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

メール/パスワード ───▶ SignupForm
                           │
                           ├─▶ Valibot safeParse
                           │         │
                           │         ├─▶ 失敗 ───▶ ValidationErrors ───▶ フィールドエラー表示
                           │         │
                           │         └─▶ 成功 ───▶ dispatch(SET_EMAIL)
                           │                              │
                           │                              ▼
                           │                      SignupContext更新
                           │
                           └─▶ signup (Server Action)
                                      │
                                      ├─▶ supabase.auth.signUp
                                      │         │
                                      │         ├─▶ 成功 ───▶ redirect(/signup/verify-email)
                                      │         │
                                      │         └─▶ 失敗 ───▶ AuthError ───▶ エラー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| page.tsx | `apps/studio.giselles.ai/app/(auth)/signup/email/page.tsx` | ソース | メールサインアップ画面のメインページコンポーネント |
| signup-form.tsx | `apps/studio.giselles.ai/app/(auth)/signup/email/signup-form.tsx` | ソース | サインアップフォームのClient Component |
| signup.ts | `apps/studio.giselles.ai/app/(auth)/signup/email/signup.ts` | ソース | サインアップのServer Action |
| validations.ts | `apps/studio.giselles.ai/app/(auth)/signup/email/validations.ts` | ソース | Valibotバリデーションスキーマ |
| context.tsx | `apps/studio.giselles.ai/app/(auth)/signup/context.tsx` | ソース | サインアップコンテキストプロバイダー |
| reducer.ts | `apps/studio.giselles.ai/app/(auth)/signup/reducer.ts` | ソース | サインアップ状態のReducer |
| types.ts | `apps/studio.giselles.ai/app/(auth)/signup/types.ts` | ソース | サインアップ関連の型定義 |
| layout.tsx | `apps/studio.giselles.ai/app/(auth)/signup/layout.tsx` | ソース | サインアップページ群のレイアウト |
| form.tsx | `apps/studio.giselles.ai/app/(auth)/components/form.tsx` | ソース | 共通フォームコンポーネント |
| auth-container.tsx | `apps/studio.giselles.ai/app/(auth)/components/auth-container.tsx` | ソース | 認証画面共通のレイアウトコンポーネント |
| error.ts | `apps/studio.giselles.ai/lib/supabase/error.ts` | ソース | 認証エラーの型定義と正規化 |
