TTMT.ManageWebGUI/src/routes/(auth)/login/index.tsx

136 lines
3.7 KiB
TypeScript
Raw Normal View History

2025-12-22 14:53:19 +07:00
import { createFileRoute, redirect, useNavigate } from '@tanstack/react-router'
2025-08-11 23:21:36 +07:00
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Button } from '@/components/ui/button'
import {
formOptions,
useForm,
} from '@tanstack/react-form'
2025-12-22 14:53:19 +07:00
import { useLogin } from '@/hooks/queries'
import { toast } from 'sonner'
2025-08-11 23:21:36 +07:00
interface LoginFormProps {
username: string
password: string
}
const defaultInput: LoginFormProps = {
username: '',
password: '',
}
const formOpts = formOptions({
defaultValues: defaultInput,
})
2025-12-22 14:53:19 +07:00
export const Route = createFileRoute('/(auth)/login/')({
2025-08-11 23:21:36 +07:00
beforeLoad: async ({ context }) => {
2025-12-22 14:53:19 +07:00
const { token } = context.auth
if (token) throw redirect({ to: '/' })
2025-08-11 23:21:36 +07:00
},
component: LoginForm,
})
function LoginForm() {
2025-12-22 14:53:19 +07:00
const navigate = useNavigate()
const loginMutation = useLogin()
2025-08-11 23:21:36 +07:00
const form = useForm({
...formOpts,
onSubmit: async ({ value }) => {
2025-12-22 14:53:19 +07:00
try {
await loginMutation.mutateAsync({
username: value.username,
password: value.password,
})
2025-08-11 23:21:36 +07:00
2025-12-22 14:53:19 +07:00
toast.success('Đăng nhập thành công!')
navigate({ to: '/' })
} catch (error: any) {
console.error('Login error:', error)
toast.error(
error.response?.data?.message || 'Tài khoản hoặc mật khẩu không đúng.'
)
2025-08-11 23:21:36 +07:00
}
},
})
return (
<Card className="max-w-md mx-auto mt-20 p-6">
<CardHeader>
<CardTitle>Đăng nhập</CardTitle>
<CardDescription>
Vui lòng nhập thông tin đăng nhập của bạn.
</CardDescription>
</CardHeader>
<CardContent>
<form
onSubmit={(e) => {
e.preventDefault()
form.handleSubmit()
}}
className="space-y-4"
>
{/* Username */}
<form.Field name="username">
{(field) => (
<div>
<Label htmlFor="username">Tên đăng nhập</Label>
<Input
id="username"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
placeholder="Tên đăng nhập"
/>
{field.state.meta.isTouched && field.state.meta.errors && (
<p className="text-sm text-red-500 mt-1">
{field.state.meta.errors}
</p>
)}
</div>
)}
</form.Field>
{/* Password */}
<form.Field name="password">
{(field) => (
<div>
<Label htmlFor="password">Mật khẩu</Label>
<Input
id="password"
type="password"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
placeholder="Mật khẩu"
/>
{field.state.meta.isTouched && field.state.meta.errors && (
<p className="text-sm text-red-500 mt-1">
{field.state.meta.errors}
</p>
)}
</div>
)}
</form.Field>
2025-12-22 14:53:19 +07:00
<Button type="submit" className="w-full" disabled={loginMutation.isPending}>
{loginMutation.isPending ? 'Đang đăng nhập...' : 'Đăng nhập'}
2025-08-11 23:21:36 +07:00
</Button>
</form>
</CardContent>
<CardFooter>
<p className="text-sm text-muted-foreground">
Chưa tài khoản? <span className="underline cursor-pointer">Đăng </span>
</p>
</CardFooter>
</Card>
)
}