登入驗證以及使用者按鈕
This commit is contained in:
140
resources/js/Pages/Auth/Login.tsx
Normal file
140
resources/js/Pages/Auth/Login.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import { Head, useForm } from "@inertiajs/react";
|
||||
import { FormEventHandler, useEffect } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import InputError from "../../Components/InputError";
|
||||
import ApplicationLogo from "../../Components/ApplicationLogo";
|
||||
|
||||
export default function Login() {
|
||||
const { data, setData, post, processing, errors, reset } = useForm({
|
||||
username: localStorage.getItem("saved_username") || "",
|
||||
password: "",
|
||||
remember: false,
|
||||
rememberUsername: localStorage.getItem("remember_username") === "true",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
reset("password");
|
||||
};
|
||||
}, []);
|
||||
|
||||
const submit: FormEventHandler = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// 處理記住帳號邏輯
|
||||
if (data.rememberUsername) {
|
||||
localStorage.setItem("saved_username", data.username);
|
||||
localStorage.setItem("remember_username", "true");
|
||||
} else {
|
||||
localStorage.removeItem("saved_username");
|
||||
localStorage.setItem("remember_username", "false");
|
||||
}
|
||||
|
||||
post(route("login"), {
|
||||
onFinish: () => reset("password"),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 relative overflow-hidden">
|
||||
<Head title="登入" />
|
||||
|
||||
{/* 動態背景裝飾 */}
|
||||
<div className="absolute top-0 -left-4 w-72 h-72 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute top-0 -right-4 w-72 h-72 bg-yellow-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute -bottom-8 left-20 w-72 h-72 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
|
||||
<div className="w-full max-w-md p-8 relative z-10">
|
||||
<div className="flex flex-col items-center mb-6">
|
||||
<ApplicationLogo className="w-40 h-40 object-contain" />
|
||||
</div>
|
||||
<div className="glass-panel p-8 rounded-2xl shadow-xl bg-white/80 backdrop-blur-md border border-white/50">
|
||||
<form onSubmit={submit} className="space-y-6">
|
||||
<div>
|
||||
<Label htmlFor="username">帳號</Label>
|
||||
<Input
|
||||
id="username"
|
||||
type="text"
|
||||
className="mt-1 block w-full bg-white/50"
|
||||
value={data.username}
|
||||
onChange={(e) => setData("username", e.target.value)}
|
||||
required
|
||||
autoFocus
|
||||
/>
|
||||
<InputError message={errors.username} className="mt-2" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="password">密碼</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
className="mt-1 block w-full bg-white/50"
|
||||
value={data.password}
|
||||
onChange={(e) => setData("password", e.target.value)}
|
||||
required
|
||||
/>
|
||||
<InputError message={errors.password} className="mt-2" />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<label className="flex items-center cursor-pointer group">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="sr-only"
|
||||
checked={data.rememberUsername}
|
||||
onChange={(e) => setData("rememberUsername", e.target.checked)}
|
||||
/>
|
||||
<div className={cn(
|
||||
"w-9 h-5 rounded-full shadow-inner transition-colors duration-300 ease-in-out",
|
||||
data.rememberUsername ? "bg-[#01ab83]" : "bg-gray-300"
|
||||
)}></div>
|
||||
<div className={cn(
|
||||
"absolute left-0.5 top-0.5 w-4 h-4 bg-white rounded-full shadow transition-transform duration-300 ease-in-out",
|
||||
data.rememberUsername ? "translate-x-4" : "translate-x-0"
|
||||
)}></div>
|
||||
</div>
|
||||
<span className="ml-2 text-sm text-gray-600 group-hover:text-gray-900 transition-colors">記住帳號</span>
|
||||
</label>
|
||||
|
||||
<label className="flex items-center cursor-pointer group">
|
||||
<span className="mr-2 text-sm text-gray-600 group-hover:text-gray-900 transition-colors">保持登入</span>
|
||||
<div className="relative">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="sr-only"
|
||||
checked={data.remember}
|
||||
onChange={(e) => setData("remember", e.target.checked)}
|
||||
/>
|
||||
<div className={cn(
|
||||
"w-9 h-5 rounded-full shadow-inner transition-colors duration-300 ease-in-out",
|
||||
data.remember ? "bg-[#01ab83]" : "bg-gray-300"
|
||||
)}></div>
|
||||
<div className={cn(
|
||||
"absolute left-0.5 top-0.5 w-4 h-4 bg-white rounded-full shadow transition-transform duration-300 ease-in-out",
|
||||
data.remember ? "translate-x-4" : "translate-x-0"
|
||||
)}></div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="w-full h-11 text-base bg-[#01ab83] hover:bg-[#018a6a] transition-all shadow-lg hover:shadow-xl"
|
||||
disabled={processing}
|
||||
>
|
||||
{processing ? "登入中..." : "登入系統"}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p className="text-center text-gray-400 text-sm mt-8">
|
||||
© 2026 小小冰室. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user