You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.8 KiB

"use client";
import { useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Truck } from "@phosphor-icons/react";
import { InputField } from "@/components/ui/input-field";
import { PrimaryButton } from "@/components/ui/primary-button";
import { ErrorBanner } from "@/components/ui/error-banner";
import { Card } from "@/components/ui/card";
import { adminLogin } from "@/lib/frontend/api-client";
import { useAuth } from "@/hooks/use-auth";
export default function LoginPageClient() {
const router = useRouter();
const searchParams = useSearchParams();
const { login } = useAuth();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (loading) return;
setLoading(true);
setError(null);
const res = await adminLogin("", username.trim(), password);
setLoading(false);
if (res.code !== 0) {
setError(res.message || "用户名或密码错误");
return;
}
login(res.data.token, res.data.user);
const redirect = searchParams.get("redirect");
router.replace(redirect || "/dashboard");
};
return (
<div className="flex min-h-[100dvh] items-center justify-center bg-bg px-4">
<div className="w-full max-w-md">
<div className="mb-6 flex items-center justify-center gap-2 text-primary">
<Truck size={32} weight="fill" />
<span className="text-2xl font-semibold"> · </span>
</div>
<Card>
<h1 className="mb-1 text-xl font-semibold"></h1>
<p className="mb-4 text-sm text-text-secondary">
</p>
{error && (
<div className="mb-4">
<ErrorBanner>{error}</ErrorBanner>
</div>
)}
<form
onSubmit={(e) => void handleSubmit(e)}
className="space-y-4"
autoComplete="off"
>
<InputField
label="用户名"
name="username"
autoComplete="off"
value={username}
disabled={loading}
onChange={(e) => setUsername(e.target.value)}
/>
<InputField
label="密码"
name="password"
type="password"
autoComplete="new-password"
value={password}
disabled={loading}
onChange={(e) => setPassword(e.target.value)}
/>
<PrimaryButton type="submit" loading={loading} className="w-full">
</PrimaryButton>
</form>
</Card>
</div>
</div>
);
}