From ceca1c51b4e7a023888957d3408ac2ab5eeaf0aa Mon Sep 17 00:00:00 2001 From: Toan Hoang Minh Date: Fri, 31 Jul 2026 11:59:35 +0700 Subject: [PATCH] feat: add login page UI --- src/app/login/page.tsx | 95 +++++++++++++++++++++++++++++++++++++ src/components/ui/input.tsx | 21 ++++++++ 2 files changed, 116 insertions(+) create mode 100644 src/app/login/page.tsx create mode 100644 src/components/ui/input.tsx diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx new file mode 100644 index 0000000..0f8b81a --- /dev/null +++ b/src/app/login/page.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { useState, type FormEvent } from "react"; +import { signIn } from "next-auth/react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +// Custom Credentials sign-in page for Auth.js v5 (src/auth.ts's +// pages.signIn points here). Internal IT-staff login only — no +// self-registration, so there's no "sign up" link. Deliberately shows a +// generic error on failure (doesn't say whether the email or the password +// was wrong) to avoid leaking which accounts exist. +export default function LoginPage() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(null); + const [submitting, setSubmitting] = useState(false); + + async function handleSubmit(event: FormEvent): Promise { + event.preventDefault(); + setError(null); + setSubmitting(true); + + try { + const result = await signIn("credentials", { + email, + password, + redirect: false, + }); + + if (!result || result.error) { + setError("Invalid email or password"); + return; + } + + window.location.href = "/"; + } finally { + setSubmitting(false); + } + } + + return ( +
+
+
+

Sign in

+

IT staff login

+
+ +
+ + setEmail(event.target.value)} + /> +
+ +
+ + setPassword(event.target.value)} + /> +
+ + {error ? ( +

+ {error} +

+ ) : null} + + +
+
+ ); +} diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..f1124ae --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,21 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Input({ className, type, ...props }: React.ComponentProps<"input">) { + return ( + + ) +} + +export { Input }