Files
ftb-project-management/apps/web/app/login/page.tsx
2026-06-25 15:21:32 +08:00

123 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useAuthStore } from '@/stores/useAuthStore';
import { Eye, EyeOff, LayoutGrid, Lock, Phone } from 'lucide-react';
export default function LoginPage() {
const router = useRouter();
const { login } = useAuthStore();
const [phone, setPhone] = useState('');
const [password, setPassword] = useState('');
const [remember, setRemember] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
if (!phone.trim() || !password.trim()) {
setError('请输入手机号和密码');
return;
}
setLoading(true);
try {
const success = await login(phone.trim(), password, remember);
if (success) {
router.push('/products');
} else {
setError('手机号或密码错误');
}
} finally {
setLoading(false);
}
};
return (
<div className="flex min-h-screen items-center justify-center bg-[var(--bg)]">
<div className="w-full max-w-sm">
<div className="mb-8 flex flex-col items-center">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[var(--accent)] shadow-lg shadow-blue-500/20">
<LayoutGrid className="h-6 w-6 text-white" strokeWidth={2} />
</div>
<h1 className="mt-4 text-[18px] font-semibold text-[var(--ink)]">FTB </h1>
<p className="mt-1 text-[13px] text-[var(--ink-muted)]">使</p>
</div>
<div className="rounded-2xl border border-[var(--line)] bg-[var(--bg-card)] p-6 shadow-[var(--shadow-md)]">
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="mb-1.5 block text-[12px] font-medium text-[var(--ink-soft)]"></label>
<div className="relative">
<Phone className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--ink-muted)]" />
<input
type="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="请输入手机号"
maxLength={11}
className="h-10 w-full rounded-lg border border-[var(--line)] bg-[var(--bg)] pl-10 pr-3 text-[14px] text-[var(--ink)] transition-all placeholder:text-[var(--ink-muted)] focus:border-[var(--accent)] focus:outline-none focus:ring-2 focus:ring-[var(--accent-ring)]"
/>
</div>
</div>
<div>
<label className="mb-1.5 block text-[12px] font-medium text-[var(--ink-soft)]"></label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--ink-muted)]" />
<input
type={showPassword ? 'text' : 'password'}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="请输入密码"
className="h-10 w-full rounded-lg border border-[var(--line)] bg-[var(--bg)] pl-10 pr-10 text-[14px] text-[var(--ink)] transition-all placeholder:text-[var(--ink-muted)] focus:border-[var(--accent)] focus:outline-none focus:ring-2 focus:ring-[var(--accent-ring)]"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-[var(--ink-muted)] hover:text-[var(--ink-soft)]"
aria-label={showPassword ? '隐藏密码' : '显示密码'}
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
</div>
<label className="flex cursor-pointer items-center gap-2">
<input
type="checkbox"
checked={remember}
onChange={(e) => setRemember(e.target.checked)}
className="h-4 w-4 rounded border-[var(--line)] text-[var(--accent)] focus:ring-[var(--accent-ring)]"
/>
<span className="text-[12px] text-[var(--ink-soft)]"></span>
</label>
{error && (
<div className="rounded-lg border border-red-100 bg-red-50 px-3 py-2 text-[12px] text-red-600">
{error}
</div>
)}
<button
type="submit"
disabled={loading}
className="h-10 w-full rounded-lg bg-[var(--accent)] text-[14px] font-medium text-white shadow-[var(--shadow-sm)] transition-all hover:bg-[var(--accent-hover)] disabled:opacity-50"
>
{loading ? '登录中...' : '登录'}
</button>
</form>
<p className="mt-4 text-center text-[11px] text-[var(--ink-muted)]">
13200132008 / Ftb@2024
</p>
</div>
</div>
</div>
);
}