1+ 'use client' ;
2+
3+ import React , { useState , useEffect } from 'react' ;
4+ import { Eye , EyeOff , Mail , Lock , Users , TrendingUp , ArrowRight , Loader2 , Moon , Sun } from 'lucide-react' ;
5+ import { Button } from '@/components/ui/button' ;
6+ import { Input } from '@/components/ui/input' ;
7+ import { Label } from '@/components/ui/label' ;
8+ import { Checkbox } from '@/components/ui/checkbox' ;
9+ import { Card , CardContent , CardDescription , CardFooter , CardHeader , CardTitle } from '@/components/ui/card' ;
10+ import { Alert , AlertDescription } from '@/components/ui/alert' ;
11+ import { useRouter } from 'next/navigation' ;
12+
13+ interface FormData {
14+ email : string ;
15+ password : string ;
16+ rememberMe : boolean ;
17+ }
18+
19+ const SignInPage = ( ) => {
20+ const router = useRouter ( ) ;
21+ const [ showPassword , setShowPassword ] = useState ( false ) ;
22+ const [ isLoading , setIsLoading ] = useState ( false ) ;
23+ const [ error , setError ] = useState ( '' ) ;
24+ const [ darkMode , setDarkMode ] = useState ( true ) ;
25+ const [ formData , setFormData ] = useState < FormData > ( {
26+ email : '' ,
27+ password : '' ,
28+ rememberMe : false
29+ } ) ;
30+
31+ useEffect ( ( ) => {
32+ // Check localStorage for theme preference on client side only
33+ if ( typeof window !== 'undefined' ) {
34+ const savedTheme = localStorage . getItem ( 'theme' ) ;
35+
36+ if ( savedTheme ) {
37+ const isDark = savedTheme === 'dark' ;
38+ setDarkMode ( isDark ) ;
39+ if ( isDark ) {
40+ document . documentElement . classList . add ( 'dark' ) ;
41+ } else {
42+ document . documentElement . classList . remove ( 'dark' ) ;
43+ }
44+ } else {
45+ // Default to dark mode
46+ setDarkMode ( true ) ;
47+ document . documentElement . classList . add ( 'dark' ) ;
48+ localStorage . setItem ( 'theme' , 'dark' ) ;
49+ }
50+ }
51+ } , [ ] ) ;
52+
53+ const toggleTheme = ( ) => {
54+ if ( typeof window !== 'undefined' ) {
55+ const newDarkMode = ! darkMode ;
56+ setDarkMode ( newDarkMode ) ;
57+
58+ if ( newDarkMode ) {
59+ document . documentElement . classList . add ( 'dark' ) ;
60+ localStorage . setItem ( 'theme' , 'dark' ) ;
61+ } else {
62+ document . documentElement . classList . remove ( 'dark' ) ;
63+ localStorage . setItem ( 'theme' , 'light' ) ;
64+ }
65+ }
66+ } ;
67+
68+ const handleInputChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
69+ const { name, value, type, checked } = e . target ;
70+ setFormData ( {
71+ ...formData ,
72+ [ name ] : type === 'checkbox' ? checked : value
73+ } ) ;
74+ if ( error ) setError ( '' ) ;
75+ } ;
76+
77+ const handleSubmit = async ( ) => {
78+ if ( ! formData . email || ! formData . password ) {
79+ setError ( 'Please fill in all required fields' ) ;
80+ return ;
81+ }
82+
83+ setIsLoading ( true ) ;
84+ setError ( '' ) ;
85+
86+ try {
87+ await new Promise ( resolve => setTimeout ( resolve , 1500 ) ) ;
88+ console . log ( 'Sign In Data:' , formData ) ;
89+ } catch {
90+ setError ( 'Invalid email or password. Please try again.' ) ;
91+ } finally {
92+ setIsLoading ( false ) ;
93+ }
94+ } ;
95+
96+ const navigateToSignUp = ( ) => {
97+ router . push ( '/signup' ) ;
98+ } ;
99+
100+ const togglePasswordVisibility = ( ) => {
101+ setShowPassword ( prev => ! prev ) ;
102+ } ;
103+
104+ return (
105+ < div className = { `min-h-screen transition-colors duration-300 ${
106+ darkMode
107+ ? 'bg-gradient-to-br from-black via-gray-900 to-gray-800'
108+ : 'bg-gradient-to-br from-gray-50 via-blue-50 to-gray-100'
109+ } flex items-center justify-center p-4 relative`} >
110+ < Button
111+ onClick = { toggleTheme }
112+ variant = "outline"
113+ size = "sm"
114+ className = { `absolute top-4 right-4 z-50 transition-all duration-300 ${
115+ darkMode
116+ ? 'bg-gray-800 border-gray-700 text-white hover:bg-gray-700'
117+ : 'bg-white border-gray-300 text-gray-900 hover:bg-gray-50'
118+ } `}
119+ >
120+ { darkMode ? < Sun className = "h-4 w-4" /> : < Moon className = "h-4 w-4" /> }
121+ </ Button >
122+ < div className = { `absolute inset-0 opacity-30 ${
123+ darkMode
124+ ? "bg-[url('data:image/svg+xml,%3Csvg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\" xmlns=\"http://www.w3.org/2000/svg\"%3E%3Cg fill=\"none\" fill-rule=\"evenodd\"%3E%3Cg fill=\"%23ffffff\" fill-opacity=\"0.02\"%3E%3Ccircle cx=\"30\" cy=\"30\" r=\"2\"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')]"
125+ : "bg-[url('data:image/svg+xml,%3Csvg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\" xmlns=\"http://www.w3.org/2000/svg\"%3E%3Cg fill=\"none\" fill-rule=\"evenodd\"%3E%3Cg fill=\"%23000000\" fill-opacity=\"0.02\"%3E%3Ccircle cx=\"30\" cy=\"30\" r=\"2\"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')]"
126+ } `} > </ div >
127+
128+ < div className = { `w-full max-w-4xl flex rounded-2xl shadow-2xl overflow-hidden border transition-all duration-300 ${
129+ darkMode
130+ ? 'bg-black/40 backdrop-blur-lg border-gray-800'
131+ : 'bg-white/80 backdrop-blur-lg border-gray-200'
132+ } `} >
133+ < div className = { `hidden lg:flex lg:w-1/2 p-12 flex-col justify-between relative overflow-hidden transition-colors duration-300 ${
134+ darkMode
135+ ? 'bg-gradient-to-br from-gray-900 to-black'
136+ : 'bg-gradient-to-br from-blue-600 to-blue-800'
137+ } `} >
138+ < div className = { `absolute top-0 right-0 w-32 h-32 rounded-full -translate-y-16 translate-x-16 ${
139+ darkMode ? 'bg-white/5' : 'bg-white/10'
140+ } `} > </ div >
141+ < div className = { `absolute bottom-0 left-0 w-24 h-24 rounded-full translate-y-12 -translate-x-12 ${
142+ darkMode ? 'bg-white/5' : 'bg-white/10'
143+ } `} > </ div >
144+
145+ < div className = "relative z-10" >
146+ < div className = "flex items-center space-x-3 mb-8" >
147+ < div className = "flex items-center" >
148+ < span className = "text-white font-bold text-2xl tracking-wide" >
149+ ROSTER< span className = "text-red-500" > RUMBLE</ span >
150+ </ span >
151+ </ div >
152+ </ div >
153+
154+ < h2 className = "text-3xl font-bold text-white mb-4" >
155+ Welcome Back, Champion
156+ </ h2 >
157+ < p className = { `text-lg leading-relaxed ${
158+ darkMode ? 'text-gray-300' : 'text-blue-100'
159+ } `} >
160+ Sign in to continue your journey to fantasy sports greatness and compete for real cash prizes.
161+ </ p >
162+ </ div >
163+
164+ < div className = "relative z-10" >
165+ < div className = "grid grid-cols-2 gap-6" >
166+ < div className = "text-center" >
167+ < div className = { `flex items-center justify-center w-12 h-12 rounded-lg mx-auto mb-3 ${
168+ darkMode ? 'bg-white/10' : 'bg-white/20'
169+ } `} >
170+ < Users className = "w-6 h-6 text-white" />
171+ </ div >
172+ < p className = "text-white font-semibold" > 10M+</ p >
173+ < p className = { `text-sm ${ darkMode ? 'text-gray-400' : 'text-blue-100' } ` } > Active Players</ p >
174+ </ div >
175+ < div className = "text-center" >
176+ < div className = { `flex items-center justify-center w-12 h-12 rounded-lg mx-auto mb-3 ${
177+ darkMode ? 'bg-white/10' : 'bg-white/20'
178+ } `} >
179+ < TrendingUp className = "w-6 h-6 text-white" />
180+ </ div >
181+ < p className = "text-white font-semibold" > ₹5000Cr+</ p >
182+ < p className = { `text-sm ${ darkMode ? 'text-gray-400' : 'text-blue-100' } ` } > Prize Pool</ p >
183+ </ div >
184+ </ div >
185+ </ div >
186+ </ div >
187+
188+
189+ < div className = "w-full lg:w-1/2 p-2 lg:p-12 flex items-center justify-center" >
190+ < div className = "w-full max-w-md" >
191+
192+ < div className = "lg:hidden flex items-center justify-center mb-8" >
193+ < div className = "flex items-center" >
194+ < span className = { `font-bold text-2xl tracking-wide ${
195+ darkMode ? 'text-white' : 'text-gray-900'
196+ } `} >
197+ ROSTER< span className = "text-red-500" > RUMBLE</ span >
198+ </ span >
199+ </ div >
200+ </ div >
201+
202+ < Card className = { `transition-colors duration-300 ${
203+ darkMode
204+ ? 'bg-gray-900/50 border-gray-800 backdrop-blur-sm'
205+ : 'bg-white/70 border-gray-200 backdrop-blur-sm'
206+ } `} >
207+ < CardHeader className = "text-center" >
208+ < CardTitle className = { `text-2xl font-bold ${ darkMode ? 'text-white' : 'text-gray-900' } ` } >
209+ Welcome Back
210+ </ CardTitle >
211+ < CardDescription className = { darkMode ? 'text-gray-400' : 'text-gray-600' } >
212+ Enter your credentials to access your account
213+ </ CardDescription >
214+ </ CardHeader >
215+
216+ < CardContent className = "space-y-6" >
217+ { error && (
218+ < Alert className = { `${
219+ darkMode
220+ ? 'bg-red-500/10 border-red-500/20'
221+ : 'bg-red-50 border-red-200'
222+ } `} >
223+ < AlertDescription className = { darkMode ? 'text-red-400' : 'text-red-600' } >
224+ { error }
225+ </ AlertDescription >
226+ </ Alert >
227+ ) }
228+
229+ < div className = "space-y-2" >
230+ < Label htmlFor = "email" className = { darkMode ? 'text-gray-300' : 'text-gray-700' } >
231+ Email Address
232+ </ Label >
233+ < div className = "relative" >
234+ < Mail className = { `absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 ${
235+ darkMode ? 'text-gray-500' : 'text-gray-400'
236+ } `} />
237+ < Input
238+ id = "email"
239+ name = "email"
240+ type = "email"
241+ value = { formData . email }
242+ onChange = { handleInputChange }
243+ className = { `pl-10 transition-colors duration-300 ${
244+ darkMode
245+ ? 'bg-gray-800/50 border-gray-700 text-white placeholder-gray-500 focus:border-blue-500'
246+ : 'bg-white border-gray-300 text-gray-900 placeholder-gray-400 focus:border-blue-500'
247+ } `}
248+ placeholder = "Enter your email"
249+ disabled = { isLoading }
250+ />
251+ </ div >
252+ </ div >
253+
254+ < div className = "space-y-2" >
255+ < Label htmlFor = "password" className = { darkMode ? 'text-gray-300' : 'text-gray-700' } >
256+ Password
257+ </ Label >
258+ < div className = "relative" >
259+ < Lock className = { `absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 ${
260+ darkMode ? 'text-gray-500' : 'text-gray-400'
261+ } `} />
262+ < Input
263+ id = "password"
264+ name = "password"
265+ type = { showPassword ? "text" : "password" }
266+ value = { formData . password }
267+ onChange = { handleInputChange }
268+ className = { `pl-10 pr-12 transition-colors duration-300 ${
269+ darkMode
270+ ? 'bg-gray-800/50 border-gray-700 text-white placeholder-gray-500 focus:border-blue-500'
271+ : 'bg-white border-gray-300 text-gray-900 placeholder-gray-400 focus:border-blue-500'
272+ } `}
273+ placeholder = "Enter your password"
274+ disabled = { isLoading }
275+ />
276+ < Button
277+ type = "button"
278+ variant = "ghost"
279+ size = "sm"
280+ className = "absolute right-0 top-0 h-full px-3 hover:bg-transparent"
281+ onClick = { togglePasswordVisibility }
282+ tabIndex = { - 1 }
283+ >
284+ { showPassword ? (
285+ < EyeOff className = { `h-5 w-5 transition-colors ${
286+ darkMode ? 'text-gray-500 hover:text-gray-300' : 'text-gray-400 hover:text-gray-600'
287+ } `} />
288+ ) : (
289+ < Eye className = { `h-5 w-5 transition-colors ${
290+ darkMode ? 'text-gray-500 hover:text-gray-300' : 'text-gray-400 hover:text-gray-600'
291+ } `} />
292+ ) }
293+ </ Button >
294+ </ div >
295+ </ div >
296+
297+ < div className = "flex items-center justify-between" >
298+ < div className = "flex items-center space-x-2" >
299+ < Checkbox
300+ id = "rememberMe"
301+ checked = { formData . rememberMe }
302+ onCheckedChange = { ( checked ) => {
303+ const isChecked = checked === true ;
304+ setFormData ( prev => ( { ...prev , rememberMe : isChecked } ) ) ;
305+ } }
306+ className = { `transition-colors ${
307+ darkMode
308+ ? 'border-gray-600 data-[state=checked]:bg-blue-600 data-[state=checked]:border-blue-600'
309+ : 'border-gray-400 data-[state=checked]:bg-blue-600 data-[state=checked]:border-blue-600'
310+ } `}
311+ />
312+ < Label
313+ htmlFor = "rememberMe"
314+ className = { `text-sm cursor-pointer transition-colors select-none ${
315+ darkMode ? 'text-gray-300 hover:text-white' : 'text-gray-700 hover:text-gray-900'
316+ } `}
317+ >
318+ Remember me
319+ </ Label >
320+ </ div >
321+ < Button
322+ variant = "link"
323+ className = { `p-0 h-auto transition-colors ${
324+ darkMode
325+ ? 'text-blue-400 hover:text-blue-300'
326+ : 'text-blue-600 hover:text-blue-700'
327+ } `}
328+ >
329+ Forgot password?
330+ </ Button >
331+ </ div >
332+
333+ < Button
334+ onClick = { handleSubmit }
335+ disabled = { isLoading }
336+ className = "w-full bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white font-semibold transition-all duration-200 disabled:opacity-50"
337+ >
338+ { isLoading ? (
339+ < >
340+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
341+ Signing In...
342+ </ >
343+ ) : (
344+ < >
345+ Sign In
346+ < ArrowRight className = "ml-2 h-4 w-4" />
347+ </ >
348+ ) }
349+ </ Button >
350+ </ CardContent >
351+
352+ < CardFooter className = "justify-center" >
353+ < p className = { `text-sm ${ darkMode ? 'text-gray-400' : 'text-gray-600' } ` } >
354+ Don't have an account?{ ' ' }
355+ < Button
356+ variant = "link"
357+ onClick = { navigateToSignUp }
358+ className = { `p-0 h-auto font-medium transition-colors ${
359+ darkMode
360+ ? 'text-blue-400 hover:text-blue-300'
361+ : 'text-blue-600 hover:text-blue-700'
362+ } `}
363+ >
364+ Sign Up
365+ </ Button >
366+ </ p >
367+ </ CardFooter >
368+ </ Card >
369+ </ div >
370+ </ div >
371+ </ div >
372+ </ div >
373+ ) ;
374+ } ;
375+
376+ export default SignInPage ;
0 commit comments