@@ -8,28 +8,26 @@ import { Input } from "@/components/ui/input"
88import { Label } from "@/components/ui/label"
99import Link from "next/link"
1010import { motion , AnimatePresence } from "framer-motion"
11- import { signIn , checkRememberMe } from "@/lib/features/auth"
11+ import { signInWithEmail , checkRememberMe } from "@/lib/features/auth"
1212import { getTranslations , getUserLanguage } from "@/lib/config"
1313import { LanguageSwitcher } from "@/components/language-switcher"
14- import {
15- EyeIcon ,
16- EyeSlashIcon ,
17- LockClosedIcon ,
18- EnvelopeIcon ,
19- ArrowRightIcon ,
20- SparklesIcon ,
21- BoltIcon ,
14+ import {
15+ EyeIcon ,
16+ EyeSlashIcon ,
17+ LockClosedIcon ,
18+ EnvelopeIcon ,
19+ ArrowRightIcon ,
20+ SparklesIcon ,
21+ BoltIcon ,
2222 ShieldCheckIcon ,
2323 CheckCircleIcon
2424} from "@heroicons/react/24/outline"
2525
2626export default function LoginPage ( ) {
2727 const router = useRouter ( )
2828 const [ email , setEmail ] = useState ( "" )
29- const [ password , setPassword ] = useState ( "" )
30- const [ rememberMe , setRememberMe ] = useState ( false )
3129 const [ error , setError ] = useState ( "" )
32- const [ showPassword , setShowPassword ] = useState ( false )
30+ const [ message , setMessage ] = useState ( "" )
3331 const [ t , setT ] = useState ( getTranslations ( "en" ) )
3432
3533 useEffect ( ( ) => {
@@ -41,23 +39,24 @@ export default function LoginPage() {
4139 router . push ( "/dashboard" )
4240 }
4341 }
44-
42+
4543 checkAuth ( )
4644 } , [ router ] )
4745
4846 const handleLogin = async ( e : React . FormEvent ) => {
4947 e . preventDefault ( )
5048 setError ( "" )
49+ setMessage ( "" )
5150
52- if ( ! email || ! password ) {
53- setError ( "Email and password are required")
51+ if ( ! email ) {
52+ setError ( t . auth . email + " is required")
5453 return
5554 }
5655
57- const result = await signIn ( email , password , rememberMe )
56+ const result = await signInWithEmail ( email )
5857
5958 if ( result . success ) {
60- router . push ( "/dashboard ")
59+ setMessage ( "Check your email for the magic link to sign in! ")
6160 } else {
6261 setError ( result . error || "Login failed" )
6362 }
@@ -73,12 +72,12 @@ export default function LoginPage() {
7372 < div className = "absolute bottom-[-10%] right-[-10%] w-[70%] h-[70%] bg-purple-600/20 rounded-full blur-[120px] animate-pulse delay-700" > </ div >
7473 < div className = "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[50%] h-[50%] bg-pink-600/10 rounded-full blur-[120px] animate-pulse delay-1000" > </ div >
7574 </ div >
76-
75+
7776 { /* Static noise texture */ }
7877 < div className = "absolute inset-0 opacity-20 pointer-events-none mix-blend-overlay bg-[url('https://grainy-gradients.vercel.app/noise.svg')]" > </ div >
7978
8079 < div className = "relative z-10 flex flex-col justify-center items-center text-white p-20 w-full" >
81- < motion . div
80+ < motion . div
8281 initial = { { opacity : 0 , x : - 50 } }
8382 animate = { { opacity : 1 , x : 0 } }
8483 transition = { { duration : 0.8 , ease : "easeOut" } }
@@ -95,7 +94,7 @@ export default function LoginPage() {
9594 < p className = "text-xs font-bold uppercase tracking-[0.4em] text-primary/80" > Innovation Lab</ p >
9695 </ div >
9796 </ div >
98-
97+
9998 < div className = "space-y-6" >
10099 < h2 className = "text-5xl font-bold leading-tight tracking-tight text-balance" >
101100 Build something < br />
@@ -112,11 +111,11 @@ export default function LoginPage() {
112111 { icon : CheckCircleIcon , title : "Collaboration" , desc : "Work with your team in real-time" } ,
113112 { icon : ShieldCheckIcon , title : "Secure & Private" , desc : "Your data is always protected" }
114113 ] . map ( ( item , idx ) => (
115- < motion . div
114+ < motion . div
116115 initial = { { opacity : 0 , y : 10 } }
117116 animate = { { opacity : 1 , y : 0 } }
118117 transition = { { delay : 0.5 + idx * 0.1 } }
119- key = { idx }
118+ key = { idx }
120119 className = "flex items-start gap-5 p-4 rounded-2xl hover:bg-white/5 transition-colors border border-transparent hover:border-white/5 group"
121120 >
122121 < div className = "rounded-xl bg-primary/10 border border-primary/20 p-3 mt-1 group-hover:bg-primary/20 transition-all" >
@@ -137,12 +136,12 @@ export default function LoginPage() {
137136 < div className = "flex-1 flex items-center justify-center p-8 bg-slate-950 relative overflow-hidden" >
138137 { /* Background glow for mobile */ }
139138 < div className = "lg:hidden absolute top-[-20%] left-[-20%] w-full h-full bg-primary/5 rounded-full blur-[100px] pointer-events-none" > </ div >
140-
139+
141140 < div className = "absolute top-8 right-8 z-20" >
142141 < LanguageSwitcher />
143142 </ div >
144143
145- < motion . div
144+ < motion . div
146145 initial = { { opacity : 0 , y : 20 } }
147146 animate = { { opacity : 1 , y : 0 } }
148147 transition = { { duration : 0.8 } }
@@ -166,7 +165,7 @@ export default function LoginPage() {
166165 < form onSubmit = { handleLogin } className = "space-y-6" >
167166 < AnimatePresence >
168167 { error && (
169- < motion . div
168+ < motion . div
170169 initial = { { opacity : 0 , height : 0 } }
171170 animate = { { opacity : 1 , height : "auto" } }
172171 exit = { { opacity : 0 , height : 0 } }
@@ -178,6 +177,19 @@ export default function LoginPage() {
178177 </ div >
179178 </ motion . div >
180179 ) }
180+ { message && (
181+ < motion . div
182+ initial = { { opacity : 0 , height : 0 } }
183+ animate = { { opacity : 1 , height : "auto" } }
184+ exit = { { opacity : 0 , height : 0 } }
185+ className = "rounded-2xl border border-green-500/50 bg-green-500/5 p-4 text-sm text-green-400 overflow-hidden"
186+ >
187+ < div className = "flex items-center gap-3" >
188+ < div className = "w-1.5 h-6 bg-green-500 rounded-full" > </ div >
189+ < p className = "font-medium" > { message } </ p >
190+ </ div >
191+ </ motion . div >
192+ ) }
181193 </ AnimatePresence >
182194
183195 < div className = "space-y-5" >
@@ -200,77 +212,30 @@ export default function LoginPage() {
200212 />
201213 </ div >
202214 </ div >
203-
204- < div className = "space-y-2" >
205- < Label htmlFor = "password" className = "text-xs font-bold uppercase tracking-widest text-slate-500 ml-1" >
206- { t . auth . password }
207- </ Label >
208- < div className = "relative group" >
209- < div className = "absolute left-4 top-1/2 -translate-y-1/2 flex items-center justify-center" >
210- < LockClosedIcon className = "h-5 w-5 text-slate-500 group-focus-within:text-primary transition-colors" />
211- </ div >
212- < Input
213- id = "password"
214- type = { showPassword ? "text" : "password" }
215- placeholder = "••••••••"
216- value = { password }
217- onChange = { ( e ) => setPassword ( e . target . value ) }
218- className = "pl-12 pr-12 h-14 bg-white/[0.03] border-white/5 hover:border-white/10 focus:border-primary/50 transition-all rounded-2xl text-lg placeholder:text-slate-600 focus:ring-0 focus:bg-white/[0.05]"
219- required
220- />
221- < button
222- type = "button"
223- onClick = { ( ) => setShowPassword ( ! showPassword ) }
224- className = "absolute right-4 top-1/2 -translate-y-1/2 text-slate-500 hover:text-white transition-colors"
225- >
226- { showPassword ? < EyeSlashIcon className = "h-5 w-5" /> : < EyeIcon className = "h-5 w-5" /> }
227- </ button >
228- </ div >
229- </ div >
230215 </ div >
231216
232- < div className = "flex items-center justify-between px-1" >
233- < label className = "flex items-center gap-3 cursor-pointer group" >
234- < div className = "relative" >
235- < input
236- type = "checkbox"
237- checked = { rememberMe }
238- onChange = { ( e ) => setRememberMe ( e . target . checked ) }
239- className = "peer appearance-none w-5 h-5 rounded-md border border-white/10 checked:bg-primary checked:border-primary transition-all cursor-pointer"
240- />
241- < CheckCircleIcon className = "absolute top-0.5 left-0.5 w-4 h-4 text-slate-950 opacity-0 peer-checked:opacity-100 transition-opacity pointer-events-none" />
242- </ div >
243- < span className = "text-sm font-medium text-slate-400 group-hover:text-slate-300 transition-colors" >
244- { t . auth . rememberMe }
245- </ span >
246- </ label >
247- < Link href = "#" className = "text-sm text-primary hover:text-white font-bold transition-colors" >
248- Forgot password?
249- </ Link >
250- </ div >
251-
252- < Button
253- type = "submit"
217+ < Button
218+ type = "submit"
254219 className = "w-full h-14 text-lg font-black uppercase tracking-widest bg-primary hover:bg-primary/90 text-slate-950 shadow-[0_0_20px_rgba(var(--primary-rgb),0.3)] hover:shadow-[0_0_30px_rgba(var(--primary-rgb),0.5)] transition-all group rounded-2xl"
255220 >
256- Sign In
221+ Send Magic Link
257222 < ArrowRightIcon className = "ml-3 h-5 w-5 group-hover:translate-x-1.5 transition-transform" />
258223 </ Button >
259224 </ form >
260225
261226 < footer className = "pt-6 space-y-6 text-center border-t border-white/5" >
262227 < p className = "text-slate-500 font-medium" >
263228 Don't have an account?{ " " }
264- < Link
265- href = "/signup"
229+ < Link
230+ href = "/signup"
266231 className = "text-white hover:text-primary font-bold underline decoration-primary/30 underline-offset-4 decoration-2 transition-all"
267232 >
268233 Sign Up
269234 </ Link >
270235 </ p >
271-
272- < Link
273- href = "/"
236+
237+ < Link
238+ href = "/"
274239 className = "inline-flex items-center gap-2 text-sm font-bold uppercase tracking-widest text-slate-600 hover:text-primary transition-all"
275240 >
276241 < span > ← Back to Home</ span >
0 commit comments