90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
"use client";
|
||
|
||
import { signin } from "@/app/lib/actions/auth";
|
||
import Link from "next/link";
|
||
import { useFormState, useFormStatus } from "react-dom";
|
||
|
||
export default function Page() {
|
||
const [errorMessage, dispatch] = useFormState(signin, undefined);
|
||
|
||
return (
|
||
<section className="text-gray-600 body-font">
|
||
<div className="container px-5 py-24 mx-auto flex flex-wrap items-center">
|
||
<div className="lg:w-3/5 md:w-1/2 md:pr-16 lg:pr-0 pr-0">
|
||
<h1 className="title-font font-medium text-3xl text-gray-900">
|
||
Slow-carb next level shoindcgoitch ethical authentic, poko scenester
|
||
</h1>
|
||
<p className="leading-relaxed mt-4">
|
||
Poke slow-carb mixtape knausgaard, typewriter street art gentrify
|
||
hammock starladder roathse. Craies vegan tousled etsy austin.
|
||
</p>
|
||
</div>
|
||
<form
|
||
action={dispatch}
|
||
className="lg:w-2/6 md:w-1/2 bg-gray-100 rounded-lg p-8 flex flex-col md:ml-auto w-full mt-10 md:mt-0"
|
||
>
|
||
<h2 className="text-gray-900 text-lg font-medium title-font mb-5">
|
||
登录
|
||
</h2>
|
||
<div className="relative mb-4">
|
||
<label
|
||
htmlFor="account"
|
||
className="leading-7 text-sm text-gray-600"
|
||
>
|
||
账号
|
||
</label>
|
||
<input
|
||
id="account"
|
||
className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
|
||
type="text"
|
||
required
|
||
name="account"
|
||
/>
|
||
</div>
|
||
<div className="relative mb-4">
|
||
<label
|
||
htmlFor="password"
|
||
className="leading-7 text-sm text-gray-600"
|
||
>
|
||
密码
|
||
</label>
|
||
<input
|
||
id="password"
|
||
className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
|
||
required
|
||
type="password"
|
||
name="password"
|
||
/>
|
||
</div>
|
||
<LoginButton className="text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg" />
|
||
<Link href="/signup" className="btn btn-link">还没有账号?可以注册一个。</Link>
|
||
{errorMessage ? (
|
||
<p className="text-xs text-red-400 mt-3">{errorMessage}</p>
|
||
) : null}
|
||
</form>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|
||
|
||
function LoginButton({ className }: { className: string | undefined }) {
|
||
const { pending } = useFormStatus();
|
||
|
||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||
if (pending) {
|
||
event.preventDefault();
|
||
}
|
||
};
|
||
|
||
return (
|
||
<button
|
||
className={className}
|
||
aria-disabled={pending}
|
||
type="submit"
|
||
onClick={handleClick}
|
||
>
|
||
登录
|
||
</button>
|
||
);
|
||
}
|