feat(auth): unify sign-in options
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { Alert, Box, Button, Checkbox, FormControlLabel, Paper, Tab, Tabs, TextField, Typography } from "@mui/material";
|
||||
import { Alert, Box, Button, Checkbox, Divider, FormControlLabel, Paper, TextField, Typography } from "@mui/material";
|
||||
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -30,7 +30,6 @@ export default function LoginPage({ initialMode = "login" }: { initialMode?: "lo
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation() as any;
|
||||
|
||||
const [tab, setTab] = useState(0);
|
||||
const [cfg, setCfg] = useState<AuthConfig | null>(null);
|
||||
|
||||
const [email, setEmail] = useState("");
|
||||
@@ -72,8 +71,8 @@ export default function LoginPage({ initialMode = "login" }: { initialMode?: "lo
|
||||
|
||||
function validate(mode: "login" | "register") {
|
||||
const errors: { email?: string; password?: string; confirmPassword?: string } = {};
|
||||
if (!email.trim()) errors.email = t("emailRequired");
|
||||
else if (!EMAIL_PATTERN.test(email.trim())) errors.email = t("invalidEmail");
|
||||
if (!email.trim()) errors.email = mode === "login" ? t("usernameOrEmailRequired") : t("emailRequired");
|
||||
else if (mode === "register" && !EMAIL_PATTERN.test(email.trim())) errors.email = t("invalidEmail");
|
||||
|
||||
if (!password) errors.password = t("passwordRequired");
|
||||
else if (mode === "register" && password.length < 8) errors.password = t("passwordTooShort");
|
||||
@@ -159,18 +158,11 @@ export default function LoginPage({ initialMode = "login" }: { initialMode?: "lo
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{initialMode === "login" ? <Tabs value={tab} onChange={(_, v) => setTab(v)} sx={{ mb: 2 }}>
|
||||
<Tab label={t("emailAndPassword")} />
|
||||
<Tab label={t("google")} />
|
||||
<Tab label={t("microsoft")} />
|
||||
</Tabs> : null}
|
||||
|
||||
{tab === 0 && (
|
||||
<Box
|
||||
component="form"
|
||||
onSubmit={(e) => { e.preventDefault(); void submit(registerMode ? "register" : "login"); }}
|
||||
sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}
|
||||
>
|
||||
<Box
|
||||
component="form"
|
||||
onSubmit={(e) => { e.preventDefault(); void submit(registerMode ? "register" : "login"); }}
|
||||
sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}
|
||||
>
|
||||
{registerMode && cfg && !allowReg ? <Alert severity="info">Registration is currently unavailable.</Alert> : null}
|
||||
{cfg?.requireEmailVerification && emailNotVerified && (
|
||||
<Alert
|
||||
@@ -184,12 +176,12 @@ export default function LoginPage({ initialMode = "login" }: { initialMode?: "lo
|
||||
{t("emailNotVerified")}
|
||||
</Alert>
|
||||
)}
|
||||
<TextField
|
||||
label={t("profileEmail")}
|
||||
type="email"
|
||||
<TextField
|
||||
label={registerMode ? t("profileEmail") : t("usernameOrEmail")}
|
||||
type={registerMode ? "email" : "text"}
|
||||
value={email}
|
||||
onChange={(e) => { setEmail(e.target.value); setFieldErrors((f) => ({ ...f, email: undefined })); }}
|
||||
autoComplete="email"
|
||||
autoComplete={registerMode ? "email" : "username"}
|
||||
autoFocus
|
||||
error={Boolean(fieldErrors.email)}
|
||||
helperText={fieldErrors.email}
|
||||
@@ -265,11 +257,17 @@ export default function LoginPage({ initialMode = "login" }: { initialMode?: "lo
|
||||
{registerMode ? t("createAccount") : t("signInTitle")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{tab === 1 && <GoogleAuthCard onSignedIn={() => { navigate(nextPath, { replace: true }); }} />}
|
||||
{tab === 2 && <MicrosoftAuthCard onSignedIn={() => { navigate(nextPath, { replace: true }); }} />}
|
||||
{!registerMode && (cfg?.googleEnabled || cfg?.microsoftEnabled) ? (
|
||||
<Box sx={{ mt: 2.5 }}>
|
||||
<Divider sx={{ mb: 2 }}>{t("or")}</Divider>
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: 1.25 }}>
|
||||
{cfg?.googleEnabled ? <GoogleAuthCard presentation="sign-in" onSignedIn={() => { navigate(nextPath, { replace: true }); }} /> : null}
|
||||
{cfg?.microsoftEnabled ? <MicrosoftAuthCard presentation="sign-in" onSignedIn={() => { navigate(nextPath, { replace: true }); }} /> : null}
|
||||
</Box>
|
||||
</Box>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
|
||||
Reference in New Issue
Block a user