account page render fix
This commit is contained in:
parent
6c0278c624
commit
170c852bb6
3 changed files with 53 additions and 38 deletions
|
|
@ -1,12 +1,7 @@
|
||||||
// app/auth/sign-in/page.tsx
|
// app/auth/sign-in/page.tsx
|
||||||
import { cookies } from "next/headers";
|
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
import SignIn from "./sign-in";
|
import SignIn from "./sign-in";
|
||||||
|
|
||||||
export default async function SignInPage() {
|
export default function SignInPage() {
|
||||||
const at = (await cookies()).get("ma_at")?.value;
|
// Do NOT redirect here. Always render the form.
|
||||||
if (at) redirect("/portal");
|
return <SignIn />;
|
||||||
|
|
||||||
// Always land on /portal after sign-in
|
|
||||||
return <SignIn nextPath="/portal" />;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,54 +2,74 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback } from "react";
|
import { useState, useCallback } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
type Props = { nextPath?: string };
|
type Props = { nextPath?: string };
|
||||||
|
|
||||||
export default function SignIn({ nextPath = "/portal" }: Props) {
|
export default function SignIn({ nextPath = "/portal" }: Props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const sp = useSearchParams();
|
||||||
|
|
||||||
|
// Respect reauth/force flags from query
|
||||||
|
const reauth = sp.get("reauth") === "1" || sp.get("force") === "1";
|
||||||
|
const next = sp.get("next") || nextPath;
|
||||||
|
|
||||||
const [identifier, setIdentifier] = useState(""); // email OR username
|
const [identifier, setIdentifier] = useState(""); // email OR username
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [err, setErr] = useState<string | null>(null);
|
const [err, setErr] = useState<string | null>(null);
|
||||||
|
|
||||||
const onSubmit = useCallback(async (e: React.FormEvent<HTMLFormElement>) => {
|
const onSubmit = useCallback(
|
||||||
e.preventDefault();
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
setErr(null);
|
e.preventDefault();
|
||||||
setLoading(true);
|
setErr(null);
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/auth/login", {
|
const res = await fetch("/api/auth/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
||||||
body: JSON.stringify({ identifier, password }),
|
body: JSON.stringify({ identifier, password }),
|
||||||
});
|
});
|
||||||
|
|
||||||
const txt = await res.text();
|
const txt = await res.text();
|
||||||
let j: any = null;
|
let j: any = null;
|
||||||
try { j = txt ? JSON.parse(txt) : null; } catch {}
|
try { j = txt ? JSON.parse(txt) : null; } catch {}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const message = j?.error || j?.message || `Sign-in failed (${res.status})`;
|
const message = j?.error || j?.message || `Sign-in failed (${res.status})`;
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success → go to intended destination (account page in reauth flow)
|
||||||
|
router.replace(next);
|
||||||
|
router.refresh();
|
||||||
|
} catch (e: any) {
|
||||||
|
setErr(e?.message || "Unable to sign in.");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Always land on the portal in this new flow
|
[identifier, password, next, router]
|
||||||
router.replace(nextPath);
|
);
|
||||||
router.refresh();
|
|
||||||
} catch (e: any) {
|
|
||||||
setErr(e?.message || "Unable to sign in.");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [identifier, password, nextPath, router]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-md rounded-lg border p-6">
|
<div className="mx-auto max-w-md rounded-lg border p-6">
|
||||||
|
{reauth && (
|
||||||
|
<div className="mb-4 rounded-md border p-3 bg-card">
|
||||||
|
<div className="font-medium">Please sign in again</div>
|
||||||
|
<div className="text-sm text-muted-foreground">
|
||||||
|
For security, we need to confirm it’s you before accessing account settings.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<h1 className="mb-1 text-2xl font-semibold">Sign In</h1>
|
<h1 className="mb-1 text-2xl font-semibold">Sign In</h1>
|
||||||
<p className="mb-6 text-sm opacity-70">Use your email <em>or</em> username with your password.</p>
|
<p className="mb-6 text-sm opacity-70">
|
||||||
|
Use your email <em>or</em> username with your password.
|
||||||
|
</p>
|
||||||
|
|
||||||
<form className="space-y-4" onSubmit={onSubmit}>
|
<form className="space-y-4" onSubmit={onSubmit}>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export default function AccountClient() {
|
||||||
For security, please sign in again before changing account details.
|
For security, please sign in again before changing account details.
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link
|
||||||
href={`/auth/sign-in?reauth=1&next=${encodeURIComponent("/portal/account")}`}
|
href={`/auth/sign-in?reauth=1&force=1&next=${encodeURIComponent("/portal/account")}`}
|
||||||
className="inline-block px-3 py-2 rounded-md border bg-accent text-background"
|
className="inline-block px-3 py-2 rounded-md border bg-accent text-background"
|
||||||
>
|
>
|
||||||
Re-authenticate
|
Re-authenticate
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue