1+ "use client" ;
2+ import React , { useState } from 'react' ;
3+ import { Input } from '@/components/ui/input' ;
4+ import { Label } from '@/components/ui/label' ;
5+ import { Button } from '@/components/ui/button' ;
6+ import { useRouter } from 'next/navigation' ;
7+
8+ const Login = ( ) => {
9+ const [ teamName , setTeamName ] = useState ( '' ) ;
10+ const [ password , setPassword ] = useState ( '' ) ;
11+ const [ error , setError ] = useState ( '' ) ;
12+ const [ isLoading , setIsLoading ] = useState ( false ) ;
13+ const [ showPassword , setShowPassword ] = useState ( false ) ;
14+ const router = useRouter ( ) ;
15+
16+
17+ const handleLogin = async ( ) => {
18+ if ( ! teamName || ! password ) {
19+ setError ( 'Please enter your team name and password.' ) ;
20+ setTimeout ( ( ) => setError ( '' ) , 4000 ) ;
21+ return ;
22+ }
23+
24+ try {
25+ setIsLoading ( true ) ;
26+ const response = await fetch ( '/api/auth/login' , {
27+ method : 'POST' ,
28+ body : JSON . stringify ( { username : teamName , password : password } ) ,
29+ headers : {
30+ 'Content-Type' : 'application/json' ,
31+ } ,
32+ } ) ;
33+
34+ const data = await response . json ( ) ;
35+ if ( response . ok && data . status ) {
36+ localStorage . setItem ( 'token' , data . token ) ;
37+ // Persist team name for navbar account menu
38+ localStorage . setItem ( 'team_name' , teamName ) ;
39+ router . push ( '/dashboard' ) ;
40+ } else {
41+ setError ( data . message || 'Login failed. Please try again.' ) ;
42+ setTimeout ( ( ) => setError ( '' ) , 5000 ) ;
43+ }
44+ } catch ( e ) {
45+ setError ( 'Something went wrong. Please try again.' ) ;
46+ setTimeout ( ( ) => setError ( '' ) , 5000 ) ;
47+ } finally {
48+ setIsLoading ( false ) ;
49+ }
50+ }
51+
52+
53+
54+ return (
55+ < div className = 'min-h-screen w-full bg-gradient-to-b from-[#0B0B0F] to-[#11111A] flex items-center justify-center px-4' >
56+ < div className = 'w-full max-w-md bg-black/40 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl p-6 md:p-8' >
57+ < div className = 'mb-6 text-center' >
58+ < h1 className = 'text-2xl font-semibold tracking-tight text-white' > Welcome</ h1 >
59+ < p className = 'text-sm text-gray-300 mt-1' > Sign in to continue to your dashboard</ p >
60+ </ div >
61+
62+ { error && (
63+ < div className = 'mb-4 rounded-md border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/60 dark:text-red-300' >
64+ { error }
65+ </ div >
66+ ) }
67+
68+ < form
69+ className = 'grid gap-4'
70+ onSubmit = { ( e ) => {
71+ e . preventDefault ( ) ;
72+ if ( ! isLoading ) handleLogin ( ) ;
73+ } }
74+ >
75+ < div className = 'grid gap-2' >
76+ < Label htmlFor = 'teamName' className = 'text-slate-200' > Team name</ Label >
77+ < Input
78+ id = 'teamName'
79+ type = 'text'
80+ placeholder = 'Enter your team name'
81+ value = { teamName }
82+ onChange = { ( e ) => setTeamName ( e . target . value ) }
83+ autoComplete = 'username'
84+ />
85+ </ div >
86+
87+ < div className = 'grid gap-2' >
88+ < Label htmlFor = 'password' className = 'text-slate-200' > Password</ Label >
89+ < div className = 'relative' >
90+ < Input
91+ id = 'password'
92+ type = { showPassword ? 'text' : 'password' }
93+ placeholder = 'Enter your password'
94+ value = { password }
95+ onChange = { ( e ) => setPassword ( e . target . value ) }
96+ autoComplete = 'current-password'
97+ className = 'pr-12'
98+ />
99+ < button
100+ type = 'button'
101+ aria-label = { showPassword ? 'Hide password' : 'Show password' }
102+ className = 'absolute inset-y-0 right-2 my-auto h-8 rounded px-2 text-xs text-slate-200 hover:bg-white/10 active:bg-white/15'
103+ onClick = { ( ) => setShowPassword ( ( s ) => ! s ) }
104+ >
105+ { showPassword ? 'Hide' : 'Show' }
106+ </ button >
107+ </ div >
108+ </ div >
109+
110+ < Button type = 'submit' className = 'w-full mt-2' disabled = { isLoading } >
111+ { isLoading ? 'Signing in...' : 'Sign in' }
112+ </ Button >
113+ </ form >
114+
115+ < p className = 'mt-6 text-center text-xs text-gray-400' >
116+ Please check your email inbox for the password.
117+ </ p >
118+ </ div >
119+ </ div >
120+ )
121+ }
122+
123+ export default Login
0 commit comments