11import Logo from '@/assets/Logo.svg'
22import useAuth from '@/hooks/useAuth'
3- import { Container , Field , Fieldset , Image , Text } from '@chakra-ui/react'
3+ import {
4+ Container ,
5+ Field ,
6+ Fieldset ,
7+ HStack ,
8+ Image ,
9+ Text ,
10+ VStack ,
11+ Box ,
12+ } from '@chakra-ui/react'
413import { Link , createFileRoute , redirect } from '@tanstack/react-router'
514import { type SubmitHandler , useForm } from 'react-hook-form'
615import { useTranslation } from 'react-i18next'
716import type { Body_login_login_access_token as AccessToken } from '../../client'
817import { DefaultButton } from '../../components/commonUI/Button'
18+ import { GoogleAuthButton } from '../../components/commonUI/GoogleAuthButton'
919import { DefaultInput } from '../../components/commonUI/Input'
1020import { emailPattern } from '../../utils'
1121
1222export const Route = createFileRoute ( '/_publicLayout/login' ) ( {
1323 component : Login ,
1424 beforeLoad : async ( ) => {
15- // NOTE: Direct localStorage access is used here because React context is not available in router guards.
16- // For all React components, use useAuthContext() from './hooks/useAuthContext' instead.
1725 const isGuest = localStorage . getItem ( 'guest_mode' ) === 'true'
1826 const isLoggedIn = Boolean ( localStorage . getItem ( 'access_token' ) ) || isGuest
1927 if ( isLoggedIn ) {
20- throw redirect ( {
21- to : '/collections' ,
22- } )
28+ throw redirect ( { to : '/collections' } )
2329 }
2430 } ,
2531} )
@@ -42,16 +48,18 @@ function Login() {
4248
4349 const onSubmit : SubmitHandler < AccessToken > = async ( data ) => {
4450 if ( isSubmitting ) return
45-
4651 resetError ( )
47-
4852 try {
4953 await loginMutation . mutateAsync ( data )
5054 } catch {
5155 // error is handled by useAuth hook
5256 }
5357 }
5458
59+ const handleGoogleLogin = ( ) => {
60+ console . log ( 'Google login clicked' )
61+ }
62+
5563 return (
5664 < Container
5765 h = "100dvh"
@@ -72,54 +80,71 @@ function Login() {
7280 cursor = "pointer"
7381 />
7482 </ Link >
75- < form onSubmit = { handleSubmit ( onSubmit ) } >
76- < Fieldset . Root maxW = "sm" >
77- < Fieldset . Content >
78- < Field . Root >
79- < Field . Label > { t ( 'general.words.email' ) } </ Field . Label >
80- < DefaultInput
81- type = "email"
82- placeholder = { t ( 'general.words.email' ) }
83- { ...register ( 'username' , {
84- required : t ( 'general.errors.usernameIsRequired' ) ,
85- pattern : emailPattern ,
86- } ) }
87- />
88- { errors . username && (
89- < Text color = "red.500" fontSize = "sm" >
90- { errors . username . message }
91- </ Text >
92- ) }
83+
84+ < VStack gap = { 2 } width = "100%" >
85+ < form onSubmit = { handleSubmit ( onSubmit ) } style = { { width : '100%' } } >
86+ < Fieldset . Root maxW = "sm" >
87+ < Fieldset . Content >
9388 < Field . Root >
94- < Field . Label > { t ( 'general.words.password ' ) } </ Field . Label >
89+ < Field . Label > { t ( 'general.words.email ' ) } </ Field . Label >
9590 < DefaultInput
96- type = "password"
97- placeholder = { t ( 'general.words.password' ) }
98- { ...register ( 'password' , {
99- required : t ( 'general.errors.passwordIsRequired' ) ,
91+ type = "email"
92+ placeholder = { t ( 'general.words.email' ) }
93+ { ...register ( 'username' , {
94+ required : t ( 'general.errors.usernameIsRequired' ) ,
95+ pattern : emailPattern ,
10096 } ) }
10197 />
102- { error && (
98+ { errors . username && (
10399 < Text color = "red.500" fontSize = "sm" >
104- { error }
100+ { errors . username . message }
105101 </ Text >
106102 ) }
103+ < Field . Root >
104+ < Field . Label > { t ( 'general.words.password' ) } </ Field . Label >
105+ < DefaultInput
106+ type = "password"
107+ placeholder = { t ( 'general.words.password' ) }
108+ { ...register ( 'password' , {
109+ required : t ( 'general.errors.passwordIsRequired' ) ,
110+ } ) }
111+ />
112+ { error && (
113+ < Text color = "red.500" fontSize = "sm" >
114+ { error }
115+ </ Text >
116+ ) }
117+ </ Field . Root >
107118 </ Field . Root >
108- </ Field . Root >
109- </ Fieldset . Content >
110- < DefaultButton type = "submit" loading = { isSubmitting } color = "fg.primary" >
111- { t ( 'general.actions.login' ) }
112- </ DefaultButton >
113- </ Fieldset . Root >
114- </ form >
115- < Text >
116- { t ( 'routes.publicLayout.login.dontHaveAccount' ) } { ' ' }
117- < Link to = "/signup" >
118- < Text as = "span" color = "blue.500" >
119- { t ( 'general.actions.signUp' ) }
119+ </ Fieldset . Content >
120+ < DefaultButton type = "submit" loading = { isSubmitting } color = "fg.primary" width = "100%" >
121+ { t ( 'general.actions.login' ) }
122+ </ DefaultButton >
123+ </ Fieldset . Root >
124+ </ form >
125+
126+ < HStack width = "100%" gap = { 2 } my = { 0.5 } >
127+ < Box flex = "1" height = "1px" bg = "bg.200" />
128+ < Text fontSize = "sm" color = "fg.muted" px = { 2 } >
129+ { t ( 'general.words.or' ) }
120130 </ Text >
121- </ Link >
122- </ Text >
131+ < Box flex = "1" height = "1px" bg = "bg.200" />
132+ </ HStack >
133+
134+ < GoogleAuthButton action = "login" onClick = { handleGoogleLogin } />
135+
136+
137+ </ VStack >
138+ < Box pl = { 0 } ml = { 0 } >
139+ < Text textAlign = "left" pl = { 0 } ml = { 0 } >
140+ { t ( 'routes.publicLayout.login.dontHaveAccount' ) } { ' ' }
141+ < Link to = "/signup" >
142+ < Text as = "span" color = "blue.500" >
143+ { t ( 'general.actions.signUp' ) }
144+ </ Text >
145+ </ Link >
146+ </ Text >
147+ </ Box >
123148 </ Container >
124149 )
125150}
0 commit comments