120 lines
4.5 KiB
JavaScript
120 lines
4.5 KiB
JavaScript
import { useState } from "react"
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
Card,
|
|
CardAction,
|
|
CardContent,
|
|
CardDescription,
|
|
CardFooter,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { login } from "@/apiv1/auth.service"
|
|
import { Link } from "react-router"
|
|
|
|
|
|
export function LoginPage({ className }) {
|
|
const [username, setUsername] = useState("")
|
|
const [password, setPassword] = useState("")
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
const [error, setError] = useState("")
|
|
const [success, setSuccess] = useState("")
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault()
|
|
setError("")
|
|
setSuccess("")
|
|
setIsLoading(true)
|
|
|
|
try {
|
|
const result = await login(username, password)
|
|
setSuccess("Login successful!")
|
|
console.log("Logged in:", result)
|
|
|
|
} catch (err) {
|
|
setError(err.detail || "Login failed. Please check your credentials.")
|
|
console.error("Login error:", err)
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={className}>
|
|
<Card className="w-full max-w-sm">
|
|
<CardHeader>
|
|
<CardTitle>Login to your account</CardTitle>
|
|
<CardDescription>
|
|
Enter your username below to login to your account
|
|
</CardDescription>
|
|
<CardAction>
|
|
<Button variant="link">
|
|
<Link to="/auth/signup">Sign Up</Link>
|
|
</Button>
|
|
</CardAction>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<form onSubmit={handleSubmit}>
|
|
<div className="flex flex-col gap-6">
|
|
{error && (
|
|
<div className="text-sm text-red-500 bg-red-50 p-2 rounded">
|
|
{error}
|
|
</div>
|
|
)}
|
|
{success && (
|
|
<div className="text-sm text-green-500 bg-green-50 p-2 rounded">
|
|
{success}
|
|
</div>
|
|
)}
|
|
<div className="grid gap-2">
|
|
<Label htmlFor="username">Username</Label>
|
|
<Input
|
|
id="username"
|
|
type="text"
|
|
placeholder="username"
|
|
value={username}
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
required
|
|
disabled={isLoading}
|
|
/>
|
|
</div>
|
|
<div className="grid gap-2">
|
|
<div className="flex items-center">
|
|
<Label htmlFor="password">Password</Label>
|
|
<a
|
|
href="#"
|
|
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
|
|
>
|
|
Forgot your password?
|
|
</a>
|
|
</div>
|
|
<Input
|
|
id="password"
|
|
type="password"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
required
|
|
disabled={isLoading}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</CardContent>
|
|
<CardFooter className="flex-col gap-2">
|
|
<Button
|
|
type="submit"
|
|
className="w-full"
|
|
onClick={handleSubmit}
|
|
disabled={isLoading}
|
|
>
|
|
{isLoading ? "Loading..." : "Login"}
|
|
</Button>
|
|
|
|
</CardFooter>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|