Skip to content

Commit 2fde636

Browse files
committed
feat: implement login page with API client integration for authentication
1 parent 219a0f3 commit 2fde636

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

frontend-nextjs/src/app/login/page.tsx

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,64 @@ import type React from "react"
44

55
import { useState } from "react"
66
import { motion } from "framer-motion"
7-
import { Eye, EyeOff } from "lucide-react"
7+
import { Eye, EyeOff, AlertCircle } from "lucide-react"
88
import { Button } from "@/components/ui/button"
99
import { Input } from "@/components/ui/input"
1010
import { Label } from "@/components/ui/label"
1111
import { Card, CardContent, CardHeader } from "@/components/ui/card"
12+
import { Alert, AlertDescription } from "@/components/ui/alert"
1213
import Link from "next/link"
14+
import { useRouter } from "next/navigation"
15+
import { loginLoginAccessToken, type BodyLoginLoginAccessToken } from "@/lib/api-client"
1316

1417
export default function LoginPage() {
1518
const [showPassword, setShowPassword] = useState(false)
1619
const [email, setEmail] = useState("")
1720
const [password, setPassword] = useState("")
21+
const [isLoading, setIsLoading] = useState(false)
22+
const [error, setError] = useState<string | null>(null)
23+
const router = useRouter()
1824

19-
const handleSubmit = (e: React.FormEvent) => {
25+
const handleSubmit = async (e: React.FormEvent) => {
2026
e.preventDefault()
21-
// Handle login logic here
22-
console.log("Login attempt:", { email, password })
27+
setIsLoading(true)
28+
setError(null)
29+
30+
try {
31+
const loginData: BodyLoginLoginAccessToken = {
32+
username: email,
33+
password: password,
34+
grant_type: "password"
35+
}
36+
37+
const response = await loginLoginAccessToken({
38+
body: loginData
39+
})
40+
41+
if (response.data?.access_token) {
42+
// Store the access token in localStorage
43+
localStorage.setItem("access_token", response.data.access_token)
44+
45+
console.log("Login successful, redirecting to dashboard...")
46+
// Redirect to dashboard page
47+
router.push("/dashboard")
48+
} else {
49+
setError("Login failed: No access token received")
50+
}
51+
} catch (err: any) {
52+
console.error("Login error:", err)
53+
54+
// Handle different types of errors
55+
if (err?.error?.detail) {
56+
setError(err.error.detail)
57+
} else if (err?.message) {
58+
setError(err.message)
59+
} else {
60+
setError("Login failed. Please check your credentials and try again.")
61+
}
62+
} finally {
63+
setIsLoading(false)
64+
}
2365
}
2466

2567
return (
@@ -47,6 +89,12 @@ export default function LoginPage() {
4789
</motion.div>
4890
</CardHeader>
4991
<CardContent>
92+
{error && (
93+
<Alert variant="destructive" className="mb-6">
94+
<AlertCircle className="h-4 w-4" />
95+
<AlertDescription>{error}</AlertDescription>
96+
</Alert>
97+
)}
5098
<form onSubmit={handleSubmit} className="space-y-6">
5199
<div className="space-y-2">
52100
<Label htmlFor="email">Email</Label>
@@ -92,8 +140,12 @@ export default function LoginPage() {
92140
Forgot password?
93141
</Link>
94142
</div>
95-
<Button type="submit" className="w-full h-12 bg-teal-600 hover:bg-teal-700 text-white font-medium">
96-
Log In
143+
<Button
144+
type="submit"
145+
className="w-full h-12 bg-teal-600 hover:bg-teal-700 text-white font-medium"
146+
disabled={isLoading}
147+
>
148+
{isLoading ? "Logging in..." : "Log In"}
97149
</Button>
98150
</form>
99151
</CardContent>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createClient, createConfig } from '@/client/client'
2+
import type { ClientOptions } from '@/client/types.gen'
3+
import * as sdk from '@/client/sdk.gen'
4+
5+
// Create a configured client instance that points to the FastAPI backend
6+
const apiClient = createClient(createConfig<ClientOptions>({
7+
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
8+
}))
9+
10+
// Export configured API functions
11+
export const loginLoginAccessToken = <ThrowOnError extends boolean = false>(
12+
options: Parameters<typeof sdk.loginLoginAccessToken<ThrowOnError>>[0]
13+
) => {
14+
return sdk.loginLoginAccessToken({ ...options, client: apiClient })
15+
}
16+
17+
// Re-export types
18+
export * from '@/client/types.gen'

0 commit comments

Comments
 (0)