2026-05-27 16:46:16 +02:00
|
|
|
import Image from "next/image";
|
2026-05-27 13:05:32 +02:00
|
|
|
import { AuthError } from "next-auth";
|
|
|
|
|
import { redirect } from "next/navigation";
|
|
|
|
|
|
|
|
|
|
import { auth, signIn } from "@/src/auth";
|
|
|
|
|
|
|
|
|
|
type LoginPageProps = {
|
|
|
|
|
searchParams?: Promise<{
|
2026-05-27 17:06:04 +02:00
|
|
|
callbackUrl?: string;
|
2026-05-27 13:05:32 +02:00
|
|
|
error?: string;
|
|
|
|
|
}>;
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-27 17:06:04 +02:00
|
|
|
function getSafeRedirectTo(value: FormDataEntryValue | null): string {
|
|
|
|
|
const raw = String(value ?? "/");
|
|
|
|
|
|
|
|
|
|
if (raw.startsWith("/") && !raw.startsWith("//")) {
|
|
|
|
|
return raw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const parsed = new URL(raw);
|
|
|
|
|
|
|
|
|
|
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
|
|
|
} catch {
|
|
|
|
|
return "/";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 13:05:32 +02:00
|
|
|
async function login(formData: FormData) {
|
|
|
|
|
"use server";
|
|
|
|
|
|
2026-05-27 15:24:29 +02:00
|
|
|
const identifier = String(formData.get("identifier") ?? "").trim();
|
|
|
|
|
|
|
|
|
|
console.log("[login-page] Submit login ricevuto", {
|
|
|
|
|
hasIdentifier: Boolean(identifier),
|
|
|
|
|
hasPassword: Boolean(formData.get("password")),
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-27 13:05:32 +02:00
|
|
|
try {
|
|
|
|
|
await signIn("credentials", {
|
2026-05-27 15:24:29 +02:00
|
|
|
identifier,
|
2026-05-27 13:05:32 +02:00
|
|
|
password: formData.get("password"),
|
2026-05-27 17:06:04 +02:00
|
|
|
redirectTo: getSafeRedirectTo(formData.get("callbackUrl")),
|
2026-05-27 13:05:32 +02:00
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
if (error instanceof AuthError) {
|
2026-05-27 15:24:29 +02:00
|
|
|
console.log("[login-page] AuthError durante login", {
|
|
|
|
|
type: error.type,
|
|
|
|
|
cause: error.cause,
|
|
|
|
|
});
|
2026-05-27 13:05:32 +02:00
|
|
|
redirect("/login?error=CredentialsSignin");
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 15:24:29 +02:00
|
|
|
console.error("[login-page] Errore inatteso durante login", {
|
|
|
|
|
error: error instanceof Error ? error.message : String(error),
|
|
|
|
|
});
|
2026-05-27 13:05:32 +02:00
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default async function LoginPage({ searchParams }: LoginPageProps) {
|
|
|
|
|
const session = await auth();
|
|
|
|
|
|
|
|
|
|
if (session?.user) {
|
|
|
|
|
redirect("/");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const params = await searchParams;
|
|
|
|
|
const hasError = params?.error === "CredentialsSignin";
|
|
|
|
|
|
|
|
|
|
return (
|
2026-05-27 16:46:16 +02:00
|
|
|
<main className="flex min-h-screen items-center justify-center bg-zinc-50 px-4 py-12">
|
|
|
|
|
<section className="w-full max-w-sm overflow-hidden rounded-lg border border-zinc-200 bg-white shadow-sm">
|
2026-05-27 16:46:16 +02:00
|
|
|
<div className="relative h-40 w-full bg-zinc-100">
|
2026-05-27 16:46:16 +02:00
|
|
|
<Image
|
|
|
|
|
src="/images/Home.jpg"
|
|
|
|
|
alt="MagRicambi"
|
|
|
|
|
fill
|
|
|
|
|
priority
|
2026-05-27 16:46:16 +02:00
|
|
|
className="object-cover"
|
2026-05-27 16:46:16 +02:00
|
|
|
sizes="(max-width: 640px) 100vw, 384px"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="p-6">
|
|
|
|
|
<div className="mb-6">
|
2026-05-27 13:05:32 +02:00
|
|
|
<h1 className="text-2xl font-semibold text-zinc-950">Accesso</h1>
|
|
|
|
|
<p className="mt-2 text-sm text-zinc-600">
|
|
|
|
|
Entra in MagRicambi con utente o email.
|
|
|
|
|
</p>
|
2026-05-27 16:46:16 +02:00
|
|
|
</div>
|
2026-05-27 13:05:32 +02:00
|
|
|
|
2026-05-27 16:46:16 +02:00
|
|
|
{hasError ? (
|
|
|
|
|
<p className="mb-4 rounded-md border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
|
|
|
|
|
Credenziali non valide oppure utente non attivo.
|
|
|
|
|
</p>
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
<form action={login} className="space-y-4">
|
|
|
|
|
<label className="block">
|
|
|
|
|
<span className="text-sm font-medium text-zinc-700">Utente o email</span>
|
|
|
|
|
<input
|
|
|
|
|
required
|
|
|
|
|
autoComplete="username"
|
|
|
|
|
name="identifier"
|
|
|
|
|
type="text"
|
|
|
|
|
className="mt-1 w-full rounded-md border border-zinc-300 px-3 py-2 text-zinc-950 outline-none transition-colors focus:border-zinc-900"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<label className="block">
|
|
|
|
|
<span className="text-sm font-medium text-zinc-700">Password</span>
|
|
|
|
|
<input
|
|
|
|
|
required
|
|
|
|
|
autoComplete="current-password"
|
|
|
|
|
name="password"
|
|
|
|
|
type="password"
|
|
|
|
|
className="mt-1 w-full rounded-md border border-zinc-300 px-3 py-2 text-zinc-950 outline-none transition-colors focus:border-zinc-900"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
type="submit"
|
|
|
|
|
className="w-full rounded-md bg-zinc-950 px-4 py-2 font-medium text-white transition-colors hover:bg-zinc-800"
|
|
|
|
|
>
|
|
|
|
|
Accedi
|
|
|
|
|
</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
2026-05-27 13:05:32 +02:00
|
|
|
</section>
|
|
|
|
|
</main>
|
|
|
|
|
);
|
|
|
|
|
}
|