124 lines
3.4 KiB
TypeScript
124 lines
3.4 KiB
TypeScript
"use client";
|
|
/**
|
|
* 邮箱注册表单
|
|
*
|
|
* 原始 Dart: lib/ui/auth/widgets/email_register_form.dart
|
|
*/
|
|
import { useState } from "react";
|
|
|
|
import { useAuthDispatch } from "@/stores/auth/auth-context";
|
|
import {
|
|
validateConfirmPassword,
|
|
validateEmail,
|
|
validatePassword,
|
|
validateUsername,
|
|
} from "@/app/auth/components/auth-validators";
|
|
|
|
import { AuthTextField } from "./auth-text-field";
|
|
import { AuthPrimaryButton } from "./auth-primary-button";
|
|
import { AuthErrorMessage } from "./auth-error-message";
|
|
import styles from "./email-form.module.css";
|
|
|
|
export interface EmailRegisterFormProps {
|
|
onSwitchToLogin: () => void;
|
|
globalError?: string | null;
|
|
isLoading?: boolean;
|
|
}
|
|
|
|
export function EmailRegisterForm({
|
|
onSwitchToLogin,
|
|
globalError,
|
|
isLoading,
|
|
}: EmailRegisterFormProps) {
|
|
const dispatch = useAuthDispatch();
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [username, setUsername] = useState("");
|
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
const [errors, setErrors] = useState<
|
|
Partial<Record<"email" | "password" | "username" | "confirmPassword", string>>
|
|
>({});
|
|
|
|
const submit = () => {
|
|
const emailErr = validateEmail(email);
|
|
const passwordErr = validatePassword(password);
|
|
const usernameErr = validateUsername(username);
|
|
const confirmErr = validateConfirmPassword(password, confirmPassword);
|
|
if (emailErr || passwordErr || usernameErr || confirmErr) {
|
|
setErrors({
|
|
email: emailErr ?? undefined,
|
|
password: passwordErr ?? undefined,
|
|
username: usernameErr ?? undefined,
|
|
confirmPassword: confirmErr ?? undefined,
|
|
});
|
|
return;
|
|
}
|
|
setErrors({});
|
|
dispatch({
|
|
type: "AuthEmailRegisterSubmitted",
|
|
email,
|
|
password,
|
|
username,
|
|
confirmPassword,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<form
|
|
className={styles.form}
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
submit();
|
|
}}
|
|
>
|
|
<AuthErrorMessage message={globalError ?? null} />
|
|
<AuthTextField
|
|
label="Username"
|
|
value={username}
|
|
onChange={setUsername}
|
|
placeholder="cozsweet_user"
|
|
autoComplete="username"
|
|
errorMessage={errors.username ?? null}
|
|
/>
|
|
<AuthTextField
|
|
label="Email"
|
|
type="email"
|
|
value={email}
|
|
onChange={setEmail}
|
|
placeholder="you@example.com"
|
|
autoComplete="email"
|
|
errorMessage={errors.email ?? null}
|
|
/>
|
|
<AuthTextField
|
|
label="Password"
|
|
type="password"
|
|
value={password}
|
|
onChange={setPassword}
|
|
placeholder="••••••••"
|
|
autoComplete="new-password"
|
|
errorMessage={errors.password ?? null}
|
|
/>
|
|
<AuthTextField
|
|
label="Confirm Password"
|
|
type="password"
|
|
value={confirmPassword}
|
|
onChange={setConfirmPassword}
|
|
placeholder="••••••••"
|
|
autoComplete="new-password"
|
|
errorMessage={errors.confirmPassword ?? null}
|
|
onSubmit={submit}
|
|
/>
|
|
<AuthPrimaryButton type="submit" isLoading={isLoading}>
|
|
Create Account
|
|
</AuthPrimaryButton>
|
|
<button
|
|
type="button"
|
|
className={styles.linkButton}
|
|
onClick={onSwitchToLogin}
|
|
>
|
|
Already have an account? <span className={styles.link}>Log in</span>
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|