# Phase 1 Signup page — how it works

This document describes [`Signup.tsx`](./Signup.tsx): a **standalone registration screen** for the `fe01` “phase1” demo flow. Use it as a spec when re-implementing the same behavior elsewhere.

## Where it lives in the app

- **Component:** `fe01/src/phase1/pages/Signup.tsx` (default export `Signup`)
- **Route:** `/phase1/signup` (see `fe01/src/App.tsx`)

This is **not** the same as the main app’s tabbed login/signup at `/signup`, which uses `SignupForm` (`fe01/src/components/auth/SignupForm.tsx`) with extra fields and optional OTP. The phase1 page is intentionally simpler.

## Dependencies

| Area | What |
|------|------|
| **Router** | `react-router-dom`: `Link`, `useNavigate` — success screen uses `navigate('/login')` (root login, not phase1). Link at bottom goes to `/phase1/login`. |
| **API** | `authService` from `@/phase1/lib/auth-service` — `register()` and `resendVerify()`. |
| **UI** | shadcn-style: `Button`, `Input`, `Label`, `Card*`, `Alert`, `Select`; icons from `lucide-react`. |

**Base URL:** `authService` uses `import.meta.env.VITE_API_URL` or falls back to `http://localhost:3000` (see `auth-service.ts`). Ensure your re-implementation uses the same env variable or your chosen API base.

## User-facing flow (two screens)

1. **Form screen** — collect name, school email, password, role → submit.
2. **Success screen** — shown when registration succeeds: explains that a verification email was sent, offers **resend verification** and **back to login**.

There is **no** auto-redirect after signup; the user must verify email via the link in mail (handled by backend + a separate verify route elsewhere, e.g. `/verify-email?userId=...&token=...`).

## State model

| State | Type | Role |
|-------|------|------|
| `email`, `password`, `fullName` | `string` | Controlled form fields |
| `role` | `'Admin' \| 'Editor' \| 'Viewer'` | Default `'Viewer'` |
| `error` | `string` | Inline validation / API error message |
| `loading` | `boolean` | Disables inputs and shows spinner on submit/resend |
| `successMsg` | `string \| null` | Message from API after successful register or resend |
| `registeredEmail` | `string \| null` | Email used for resend; together with `successMsg` gates the success UI |

**Success UI condition:** `successMsg && registeredEmail` — both must be set after a successful `register()`.

## Role picker

- **Canonical values** sent to API: `Admin`, `Editor`, `Viewer` (must match backend).
- **Display:** Vietnamese labels + icons + a one-line **description** under the select (`ROLE_OPTIONS` array in the component).

Re-implementing: keep the **API values** exactly as the backend expects; only labels/descriptions are presentation.

## Client-side validation (before `register`)

Order in `handleSubmit`:

1. Clear `error`.
2. `fullName` — non-empty after trim.
3. `email` — non-empty after trim.
4. **Domain check** — `validateDomain()`:
   - Must contain `@`.
   - Part after `@` (lower case, trimmed) must equal one of **`ump.edu.vn`** or **`umc.edu.vn`** (hardcoded hint list `ALLOWED_DOMAINS_HINT`).
5. `password` — length ≥ 8.

**Important:** This list is a **UX hint**. The file comment states the server re-validates using `SystemSettings` / `Auth.AllowedEmailDomains`. Your copy can change the hint list, but must stay aligned with server policy.

**On submit:** email is sent as `email.trim().toLowerCase()`; `fullName` is `fullName.trim()`.

## API: `register`

**Call:** `authService.register({ email, password, fullName, role })`

**HTTP:** `POST {API_URL}/auth/register`

**Headers:** `Content-Type: application/json`, `X-Client-Origin: window.location.origin`

**Body:** JSON `{ email, password, fullName, role }` with `role` one of `Admin` | `Editor` | `Viewer`.

**On failure (`!res.ok`):** `authService` returns `{ success: false, error: string }` — page sets `error` and stops.

**On success:** `{ success: true, userId, email, role, emailSent, message }` — page sets `registeredEmail` from `res.email`, `successMsg` from `res.message`, does **not** set tokens (registration does not log the user in).

## API: resend verification

**When:** User is on success screen and clicks “Gửi lại email xác nhận”.

**Call:** `authService.resendVerify(registeredEmail)`

**HTTP:** `POST {API_URL}/auth/resend-verify` with JSON `{ email }`, same `X-Client-Origin` pattern.

**On response:** Page updates `successMsg` with `res.message` (does not clear the success layout).

## Error display

- Errors render in a destructive `Alert` above the submit button.
- Success screen uses a non-destructive `Alert` for `successMsg`.

## Styling / layout notes

- **Form:** centered card on `bg-muted/20`, max width `max-w-md`.
- **Success:** full-height centered layout with gradient background and slightly richer card styling (backdrop blur, green mail icon).
- **Accessibility:** labels use `htmlFor` matching input `id`; password field has `minLength={8}` and `required` in addition to JS checks.

## Checklist for a faithful re-implementation

- [ ] Same route or intentionally different — document if you move it.
- [ ] `register` + `resendVerify` endpoints, payloads, and headers (`X-Client-Origin`, `credentials: 'include'` if cookies matter for your stack).
- [ ] Two-step UI: form → “check your email” with resend + login navigation.
- [ ] Client validation order and domain hint list (or replace hint with server-driven list if you add an endpoint).
- [ ] Role enum matches backend; Vietnamese copy optional.
- [ ] Distinguish this simple flow from `SignupForm` (OTP/extra fields) if both exist in the product.

## Related files

- `fe01/src/phase1/lib/auth-service.ts` — `register`, `resendVerify`, `verifyEmail`
- `fe01/src/App.tsx` — route wiring
- `fe01/src/components/auth/SignupForm.tsx` — richer signup used on main `/login` + `/signup` (different product path)
