"use client" ;
import { useState } from "react" ;
import {
LogIn,
Mail,
Lock,
Eye,
EyeOff,
Loader2,
AlertCircle,
} from "lucide-react" ;
import { Button } from "@/components/ui/button" ;
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { Input } from "@/components/ui/input" ;
import { Label } from "@/components/ui/label" ;
import { Checkbox } from "@/components/ui/checkbox" ;
import { Separator } from "@/components/ui/separator" ;
import { Alert, AlertDescription } from "@/components/ui/alert" ;
import { cn } from "@/lib/utils" ;
export const title = "React Dialog Block Login" ;
export default function DialogLogin () {
const [ open , setOpen ] = useState ( false );
const [ email , setEmail ] = useState ( "" );
const [ password , setPassword ] = useState ( "" );
const [ showPassword , setShowPassword ] = useState ( false );
const [ rememberMe , setRememberMe ] = useState ( false );
const [ isLoading , setIsLoading ] = useState ( false );
const [ error , setError ] = useState < string | null >( null );
const handleSubmit = async ( e : React . FormEvent ) => {
e. preventDefault ();
setError ( null );
if ( ! email || ! password) {
setError ( "Please enter your email and password." );
return ;
}
setIsLoading ( true );
// Simulate login
await new Promise (( resolve ) => setTimeout (resolve, 1500 ));
// Simulate error for demo (in real app, this would be actual auth)
if (password. length < 6 ) {
setError ( "Invalid email or password. Please try again." );
setIsLoading ( false );
return ;
}
setIsLoading ( false );
setOpen ( false );
};
const handleSocialLogin = async ( provider : string ) => {
setIsLoading ( true );
setError ( null );
// Simulate social login redirect
await new Promise (( resolve ) => setTimeout (resolve, 1000 ));
setIsLoading ( false );
// In real app: redirect to OAuth provider
};
const handleClose = () => {
setOpen ( false );
setTimeout (() => {
setEmail ( "" );
setPassword ( "" );
setError ( null );
setRememberMe ( false );
}, 200 );
};
return (
< Dialog open = {open} onOpenChange = {setOpen}>
< div className = "flex min-h-[350px] items-center justify-center" >
< DialogTrigger asChild >
< Button variant = "outline" >
< LogIn className = "mr-2 h-4 w-4" />
Sign In
</ Button >
</ DialogTrigger >
</ div >
< DialogContent className = "sm:max-w-md" >
< DialogHeader >
< DialogTitle className = "text-center" >Welcome back</ DialogTitle >
< DialogDescription className = "text-center" >
Sign in to your account to continue
</ DialogDescription >
</ DialogHeader >
< div className = "space-y-4 py-4" >
{ /* Social Login Buttons */ }
< div className = "grid grid-cols-2 gap-3" >
< Button
variant = "outline"
onClick = {() => handleSocialLogin ( "google" )}
disabled = {isLoading}
>
< svg className = "mr-2 h-4 w-4" viewBox = "0 0 24 24" >
< path
fill = "currentColor"
d = "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
/>
< path
fill = "currentColor"
d = "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
/>
< path
fill = "currentColor"
d = "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
/>
< path
fill = "currentColor"
d = "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
/>
</ svg >
Google
</ Button >
< Button
variant = "outline"
onClick = {() => handleSocialLogin ( "github" )}
disabled = {isLoading}
>
< svg className = "mr-2 h-4 w-4" fill = "currentColor" viewBox = "0 0 24 24" >
< path d = "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</ svg >
GitHub
</ Button >
</ div >
< div className = "relative" >
< div className = "absolute inset-0 flex items-center" >
< Separator className = "w-full" />
</ div >
< div className = "relative flex justify-center text-xs uppercase" >
< span className = "bg-background px-2 text-muted-foreground" >
Or continue with
</ span >
</ div >
</ div >
{ /* Error Alert */ }
{error && (
< Alert variant = "destructive" >
< AlertCircle className = "h-4 w-4" />
< AlertDescription >{error}</ AlertDescription >
</ Alert >
)}
{ /* Login Form */ }
< form onSubmit = {handleSubmit} className = "space-y-4" >
< div className = "space-y-2" >
< Label htmlFor = "email" >Email</ Label >
< div className = "relative" >
< Mail className = "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
< Input
id = "email"
type = "email"
placeholder = "[email protected] "
value = {email}
onChange = {( e ) => setEmail (e.target.value)}
className = "pl-9"
disabled = {isLoading}
/>
</ div >
</ div >
< div className = "space-y-2" >
< div className = "flex items-center justify-between" >
< Label htmlFor = "password" >Password</ Label >
< Button
type = "button"
variant = "link"
size = "sm"
className = "h-auto p-0 text-xs"
>
Forgot password?
</ Button >
</ div >
< div className = "relative" >
< Lock className = "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
< Input
id = "password"
type = {showPassword ? "text" : "password" }
placeholder = "Enter your password"
value = {password}
onChange = {( e ) => setPassword (e.target.value)}
className = "pl-9 pr-9"
disabled = {isLoading}
/>
< Button
type = "button"
variant = "ghost"
size = "icon"
className = "absolute right-0 top-0 h-full px-3 hover:bg-transparent"
onClick = {() => setShowPassword ( ! showPassword)}
>
{showPassword ? (
< EyeOff className = "h-4 w-4 text-muted-foreground" />
) : (
< Eye className = "h-4 w-4 text-muted-foreground" />
)}
</ Button >
</ div >
</ div >
< div className = "flex items-center gap-2" >
< Checkbox
id = "remember"
checked = {rememberMe}
onCheckedChange = {( checked ) => setRememberMe (checked === true )}
disabled = {isLoading}
/>
< Label htmlFor = "remember" className = "text-sm font-normal cursor-pointer" >
Remember me for 30 days
</ Label >
</ div >
< Button type = "submit" className = "w-full" disabled = {isLoading}>
{isLoading ? (
<>
< Loader2 className = "mr-2 h-4 w-4 animate-spin" />
Signing in...
</>
) : (
<>
< LogIn className = "mr-2 h-4 w-4" />
Sign in
</>
)}
</ Button >
</ form >
< p className = "text-center text-sm text-muted-foreground" >
Don't have an account?{ " " }
< Button variant = "link" className = "h-auto p-0 text-sm" >
Sign up
</ Button >
</ p >
</ div >
</ DialogContent >
</ Dialog >
);
}