11"use client" ;
2- import Checkbox from "@/components/form/input/Checkbox" ;
32import Input from "@/components/form/input/InputField" ;
43import Label from "@/components/form/Label" ;
5- import Button from "@/components/ui/button/Button " ;
4+ import SpinnerButton from "@/components/ui/button/SpinnerButton " ;
65import { ChevronLeftIcon , EyeCloseIcon , EyeIcon } from "@/icons" ;
76import Link from "next/link" ;
8- import React , { useState } from "react" ;
7+ import React , { useState , useEffect } from "react" ;
8+ import { useForm , type SubmitHandler } from "react-hook-form" ;
9+ import useAuth , { isLoggedIn } from "@/hooks/useAuth" ;
10+ import { useRouter } from "next/navigation" ;
11+
12+ type FormData = {
13+ email : string ;
14+ password : string ;
15+ } ;
916
1017export default function SignInForm ( ) {
1118 const [ showPassword , setShowPassword ] = useState ( false ) ;
12- const [ isChecked , setIsChecked ] = useState ( false ) ;
19+ const { loginMutation, resetError } = useAuth ( ) ;
20+ const router = useRouter ( ) ;
21+
22+ // Redirect if already logged in
23+ useEffect ( ( ) => {
24+ if ( isLoggedIn ( ) ) {
25+ router . push ( "/" ) ;
26+ }
27+ } , [ router ] ) ;
28+
29+ const {
30+ register,
31+ handleSubmit,
32+ formState : { errors } ,
33+ } = useForm < FormData > ( {
34+ mode : "onChange" ,
35+ defaultValues : { email : "" , password : "" } ,
36+ } ) ;
37+
38+ const onSubmit : SubmitHandler < FormData > = ( data ) => {
39+ resetError ( ) ;
40+ loginMutation . mutate (
41+ { username : data . email , password : data . password } ,
42+ {
43+ onSuccess : ( ) => {
44+ router . push ( "/" ) ; // Redirect after login
45+ } ,
46+ }
47+ ) ;
48+ } ;
49+
1350 return (
1451 < div className = "flex flex-col flex-1 lg:w-1/2 w-full" >
1552 < div className = "w-full max-w-md sm:pt-10 mx-auto mb-5" >
@@ -18,135 +55,89 @@ export default function SignInForm() {
1855 className = "inline-flex items-center text-sm text-gray-500 transition-colors hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
1956 >
2057 < ChevronLeftIcon />
21- Back to dashboard
58+ Back to home
2259 </ Link >
2360 </ div >
2461 < div className = "flex flex-col justify-center flex-1 w-full max-w-md mx-auto" >
25- < div >
26- < div className = "mb-5 sm:mb-8" >
27- < h1 className = "mb-2 font-semibold text-gray-800 text-title-sm dark:text-white/90 sm:text-title-md" >
28- Sign In
29- </ h1 >
30- < p className = "text-sm text-gray-500 dark:text-gray-400" >
31- Enter your email and password to sign in!
32- </ p >
33- </ div >
34- < div >
35- < div className = "grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-5" >
36- < button className = "inline-flex items-center justify-center gap-3 py-3 text-sm font-normal text-gray-700 transition-colors bg-gray-100 rounded-lg px-7 hover:bg-gray-200 hover:text-gray-800 dark:bg-white/5 dark:text-white/90 dark:hover:bg-white/10" >
37- < svg
38- width = "20"
39- height = "20"
40- viewBox = "0 0 20 20"
41- fill = "none"
42- xmlns = "http://www.w3.org/2000/svg"
43- >
44- < path
45- d = "M18.7511 10.1944C18.7511 9.47495 18.6915 8.94995 18.5626 8.40552H10.1797V11.6527H15.1003C15.0011 12.4597 14.4654 13.675 13.2749 14.4916L13.2582 14.6003L15.9087 16.6126L16.0924 16.6305C17.7788 15.1041 18.7511 12.8583 18.7511 10.1944Z"
46- fill = "#4285F4"
47- />
48- < path
49- d = "M10.1788 18.75C12.5895 18.75 14.6133 17.9722 16.0915 16.6305L13.274 14.4916C12.5201 15.0068 11.5081 15.3666 10.1788 15.3666C7.81773 15.3666 5.81379 13.8402 5.09944 11.7305L4.99473 11.7392L2.23868 13.8295L2.20264 13.9277C3.67087 16.786 6.68674 18.75 10.1788 18.75Z"
50- fill = "#34A853"
51- />
52- < path
53- d = "M5.10014 11.7305C4.91165 11.186 4.80257 10.6027 4.80257 9.99992C4.80257 9.3971 4.91165 8.81379 5.09022 8.26935L5.08523 8.1534L2.29464 6.02954L2.20333 6.0721C1.5982 7.25823 1.25098 8.5902 1.25098 9.99992C1.25098 11.4096 1.5982 12.7415 2.20333 13.9277L5.10014 11.7305Z"
54- fill = "#FBBC05"
55- />
56- < path
57- d = "M10.1789 4.63331C11.8554 4.63331 12.9864 5.34303 13.6312 5.93612L16.1511 3.525C14.6035 2.11528 12.5895 1.25 10.1789 1.25C6.68676 1.25 3.67088 3.21387 2.20264 6.07218L5.08953 8.26943C5.81381 6.15972 7.81776 4.63331 10.1789 4.63331Z"
58- fill = "#EB4335"
59- />
60- </ svg >
61- Sign in with Google
62- </ button >
63- < button className = "inline-flex items-center justify-center gap-3 py-3 text-sm font-normal text-gray-700 transition-colors bg-gray-100 rounded-lg px-7 hover:bg-gray-200 hover:text-gray-800 dark:bg-white/5 dark:text-white/90 dark:hover:bg-white/10" >
64- < svg
65- width = "21"
66- className = "fill-current"
67- height = "20"
68- viewBox = "0 0 21 20"
69- fill = "none"
70- xmlns = "http://www.w3.org/2000/svg"
71- >
72- < path d = "M15.6705 1.875H18.4272L12.4047 8.75833L19.4897 18.125H13.9422L9.59717 12.4442L4.62554 18.125H1.86721L8.30887 10.7625L1.51221 1.875H7.20054L11.128 7.0675L15.6705 1.875ZM14.703 16.475H16.2305L6.37054 3.43833H4.73137L14.703 16.475Z" />
73- </ svg >
74- Sign in with X
75- </ button >
62+ < div className = "mb-5 sm:mb-8" >
63+ < h1 className = "mb-2 font-semibold text-gray-800 text-title-sm dark:text-white/90 sm:text-title-md" >
64+ Sign In
65+ </ h1 >
66+ < p className = "text-sm text-gray-500 dark:text-gray-400" >
67+ Enter your email and password to sign in!
68+ </ p >
69+ </ div >
70+
71+ < form onSubmit = { handleSubmit ( onSubmit ) } >
72+ < div className = "space-y-6" >
73+ < div >
74+ < Label >
75+ Email < span className = "text-error-500" > *</ span >
76+ </ Label >
77+ < Input
78+ type = "email"
79+ 80+ { ...register ( "email" , { required : "Email is required" } ) }
81+ error = { ! ! errors . email }
82+ hint = { errors . email ?. message }
83+ />
7684 </ div >
77- < div className = "relative py-3 sm:py-5" >
78- < div className = "absolute inset-0 flex items-center" >
79- < div className = "w-full border-t border-gray-200 dark:border-gray-800" > </ div >
80- </ div >
81- < div className = "relative flex justify-center text-sm" >
82- < span className = "p-2 text-gray-400 bg-white dark:bg-gray-900 sm:px-5 sm:py-2" >
83- Or
85+
86+ < div >
87+ < Label >
88+ Password < span className = "text-error-500" > *</ span >
89+ </ Label >
90+ < div className = "relative" >
91+ < Input
92+ type = { showPassword ? "text" : "password" }
93+ placeholder = "Enter your password"
94+ { ...register ( "password" , { required : "Password is required" } ) }
95+ error = { ! ! errors . password }
96+ hint = { errors . password ?. message }
97+ />
98+ < span
99+ onClick = { ( ) => setShowPassword ( ! showPassword ) }
100+ className = "absolute z-30 -translate-y-1/2 cursor-pointer right-4 top-1/2"
101+ >
102+ { showPassword ? (
103+ < EyeIcon className = "fill-gray-500 dark:fill-gray-400" />
104+ ) : (
105+ < EyeCloseIcon className = "fill-gray-500 dark:fill-gray-400" />
106+ ) }
84107 </ span >
85108 </ div >
86109 </ div >
87- < form >
88- < div className = "space-y-6" >
89- < div >
90- < Label >
91- Email < span className = "text-error-500" > *</ span > { " " }
92- </ Label >
93- < Input placeholder = "[email protected] " type = "email" /> 94- </ div >
95- < div >
96- < Label >
97- Password < span className = "text-error-500" > *</ span > { " " }
98- </ Label >
99- < div className = "relative" >
100- < Input
101- type = { showPassword ? "text" : "password" }
102- placeholder = "Enter your password"
103- />
104- < span
105- onClick = { ( ) => setShowPassword ( ! showPassword ) }
106- className = "absolute z-30 -translate-y-1/2 cursor-pointer right-4 top-1/2"
107- >
108- { showPassword ? (
109- < EyeIcon className = "fill-gray-500 dark:fill-gray-400" />
110- ) : (
111- < EyeCloseIcon className = "fill-gray-500 dark:fill-gray-400" />
112- ) }
113- </ span >
114- </ div >
115- </ div >
116- < div className = "flex items-center justify-between" >
117- < div className = "flex items-center gap-3" >
118- < Checkbox checked = { isChecked } onChange = { setIsChecked } />
119- < span className = "block font-normal text-gray-700 text-theme-sm dark:text-gray-400" >
120- Keep me logged in
121- </ span >
122- </ div >
123- < Link
124- href = "/reset-password"
125- className = "text-sm text-brand-500 hover:text-brand-600 dark:text-brand-400"
126- >
127- Forgot password?
128- </ Link >
129- </ div >
130- < div >
131- < Button className = "w-full" size = "sm" >
132- Sign in
133- </ Button >
134- </ div >
135- </ div >
136- </ form >
137110
138- < div className = "mt-5" >
139- < p className = "text-sm font-normal text-center text-gray-700 dark:text-gray-400 sm:text-start" >
140- Don't have an account? { "" }
141- < Link
142- href = "/signup "
143- className = "text-brand-500 hover:text-brand-600 dark:text-brand-400"
144- >
145- Sign Up
146- </ Link >
147- </ p >
111+ < div >
112+ < SpinnerButton
113+ className = "w-full"
114+ size = "sm"
115+ type = "submit "
116+ loading = { loginMutation . isLoading }
117+ disabled = { loginMutation . isLoading }
118+ >
119+ Sign In
120+ </ SpinnerButton >
148121 </ div >
122+
123+ { loginMutation . isError && (
124+ < p className = "text-error-500 text-sm" >
125+ { loginMutation . error ?. message ?? "Login failed" }
126+ </ p >
127+ ) }
149128 </ div >
129+ </ form >
130+
131+ < div className = "mt-5" >
132+ < p className = "text-sm font-normal text-center text-gray-700 dark:text-gray-400 sm:text-start" >
133+ Don't have an account?{ " " }
134+ < Link
135+ href = "/signup"
136+ className = "text-brand-500 hover:text-brand-600 dark:text-brand-400"
137+ >
138+ Sign Up
139+ </ Link >
140+ </ p >
150141 </ div >
151142 </ div >
152143 </ div >
0 commit comments