|
|
@@ -6,13 +6,8 @@ import { Link } from "@/i18n/navigation";
|
|
|
import { useEffect, useState } from "react";
|
|
|
import { useAuth } from "@/providers/auth-provider";
|
|
|
import { ApiError } from "@/lib/api";
|
|
|
-import { CountryCombobox } from "@/components/country-combobox";
|
|
|
import { isRegisterPasswordValid } from "@/lib/password-rules";
|
|
|
-import {
|
|
|
- fetchRegisterCountries,
|
|
|
- sendRegisterVerificationCode,
|
|
|
- type CountryOption,
|
|
|
-} from "@/lib/register-api";
|
|
|
+import { sendRegisterVerificationCode } from "@/lib/register-api";
|
|
|
|
|
|
const SEND_CODE_COOLDOWN_SEC = 60;
|
|
|
|
|
|
@@ -20,12 +15,8 @@ export default function RegisterPage() {
|
|
|
const t = useTranslations("auth");
|
|
|
const router = useRouter();
|
|
|
const { register, logout } = useAuth();
|
|
|
- const [countries, setCountries] = useState<CountryOption[]>([]);
|
|
|
- const [countriesLoading, setCountriesLoading] = useState(true);
|
|
|
- const [country, setCountry] = useState("");
|
|
|
const [email, setEmail] = useState("");
|
|
|
const [password, setPassword] = useState("");
|
|
|
- const [name, setName] = useState("");
|
|
|
const [code, setCode] = useState("");
|
|
|
const [err, setErr] = useState<string | null>(null);
|
|
|
const [sendCooldown, setSendCooldown] = useState(0);
|
|
|
@@ -35,30 +26,11 @@ export default function RegisterPage() {
|
|
|
const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
|
|
|
const canSendCode = emailValid && !sendingCode && sendCooldown <= 0;
|
|
|
const canSubmit =
|
|
|
- country.length > 0 &&
|
|
|
email.trim().length > 0 &&
|
|
|
code.trim().length > 0 &&
|
|
|
- name.trim().length > 0 &&
|
|
|
password.length > 0 &&
|
|
|
!submitting;
|
|
|
|
|
|
- useEffect(() => {
|
|
|
- let cancelled = false;
|
|
|
- (async () => {
|
|
|
- try {
|
|
|
- const list = await fetchRegisterCountries();
|
|
|
- if (!cancelled) setCountries(list);
|
|
|
- } catch {
|
|
|
- if (!cancelled) setCountries([]);
|
|
|
- } finally {
|
|
|
- if (!cancelled) setCountriesLoading(false);
|
|
|
- }
|
|
|
- })();
|
|
|
- return () => {
|
|
|
- cancelled = true;
|
|
|
- };
|
|
|
- }, []);
|
|
|
-
|
|
|
useEffect(() => {
|
|
|
if (sendCooldown <= 0) return;
|
|
|
const id = window.setInterval(() => {
|
|
|
@@ -104,10 +76,10 @@ export default function RegisterPage() {
|
|
|
}
|
|
|
setSubmitting(true);
|
|
|
const r = await register({
|
|
|
- country,
|
|
|
+ country: "CN",
|
|
|
email: email.trim(),
|
|
|
password,
|
|
|
- name: name.trim(),
|
|
|
+ name: "学员",
|
|
|
code: code.trim(),
|
|
|
});
|
|
|
if (!r.ok) {
|
|
|
@@ -147,22 +119,6 @@ export default function RegisterPage() {
|
|
|
<h1 className="font-serif text-2xl font-semibold text-[var(--navy)]">{t("registerTitle")}</h1>
|
|
|
<p className="mt-2 text-sm text-[var(--muted)]">{t("registerEmailOnlyHint")}</p>
|
|
|
<form onSubmit={onSubmit} className="mt-8 space-y-4">
|
|
|
- <div>
|
|
|
- <label className="text-sm font-medium">{t("country")}</label>
|
|
|
- <CountryCombobox
|
|
|
- countries={countries}
|
|
|
- value={country}
|
|
|
- onValueChange={setCountry}
|
|
|
- loading={countriesLoading}
|
|
|
- disabled={!countriesLoading && countries.length === 0}
|
|
|
- labels={{
|
|
|
- placeholder: t("selectCountry"),
|
|
|
- loading: t("loadingCountries"),
|
|
|
- searchPlaceholder: t("countrySearchPlaceholder"),
|
|
|
- noResults: t("countryNoResults"),
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
<div>
|
|
|
<label className="text-sm font-medium">{t("email")}</label>
|
|
|
<input
|
|
|
@@ -208,20 +164,6 @@ export default function RegisterPage() {
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div>
|
|
|
- <label className="text-sm font-medium">{t("name")}</label>
|
|
|
- <input
|
|
|
- required
|
|
|
- value={name}
|
|
|
- onChange={(e) => {
|
|
|
- setName(e.target.value);
|
|
|
- if (err) setErr(null);
|
|
|
- }}
|
|
|
- onBlur={() => setName((v) => v.trim())}
|
|
|
- autoComplete="name"
|
|
|
- className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
|
|
|
- />
|
|
|
- </div>
|
|
|
<div>
|
|
|
<label className="text-sm font-medium">{t("password")}</label>
|
|
|
<input
|