"use client" ;
import { useState } from "react" ;
import { Send, Check, Loader2 } from "lucide-react" ;
import { Button } from "@/components/ui/button" ;
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { Input } from "@/components/ui/input" ;
import { Avatar, AvatarFallback } from "@/components/ui/avatar" ;
import { cn } from "@/lib/utils" ;
const recentContacts = [
{ id: "1" , name: "Alex M." , initials: "AM" },
{ id: "2" , name: "Sarah K." , initials: "SK" },
{ id: "3" , name: "Mike R." , initials: "MR" },
{ id: "4" , name: "Emma L." , initials: "EL" },
];
export const title = "React Dialog Block Quick Transfer" ;
export default function DialogQuickTransfer () {
const [ open , setOpen ] = useState ( false );
const [ selected , setSelected ] = useState < string | null >( null );
const [ amount , setAmount ] = useState ( "" );
const [ sending , setSending ] = useState ( false );
const [ sent , setSent ] = useState ( false );
const selectedContact = recentContacts. find (( c ) => c.id === selected);
const handleSend = async () => {
if ( ! selected || ! amount) return ;
setSending ( true );
await new Promise (( r ) => setTimeout (r, 1500 ));
setSending ( false );
setSent ( true );
};
const handleClose = () => {
setOpen ( false );
setTimeout (() => {
setSelected ( null );
setAmount ( "" );
setSending ( false );
setSent ( false );
}, 200 );
};
return (
< Dialog open = {open} onOpenChange = {setOpen}>
< div className = "flex min-h-[350px] items-center justify-center" >
< DialogTrigger asChild >
< Button variant = "outline" >
< Send className = "mr-2 h-4 w-4" />
Quick Transfer
</ Button >
</ DialogTrigger >
</ div >
< DialogContent style = {{ maxWidth: "384px" }}>
{sent ? (
< div className = "flex flex-col items-center justify-center py-6 text-center" >
< Check className = "h-8 w-8 text-primary" />
< h3 className = "mt-4 text-lg font-medium" >Transfer Sent</ h3 >
< p className = "mt-1 text-sm text-muted-foreground" >
${amount} to {selectedContact?.name}
</ p >
< Button onClick = {handleClose} className = "mt-6" >
Done
</ Button >
</ div >
) : (
<>
< DialogHeader >
< DialogTitle >Send Money</ DialogTitle >
< DialogDescription >
Select a contact and enter amount
</ DialogDescription >
</ DialogHeader >
< div className = "py-4 space-y-4" >
{ /* Recent contacts */ }
< div className = "space-y-2" >
< p className = "text-sm text-muted-foreground" >Recent</ p >
< div className = "grid grid-cols-4 gap-2" >
{recentContacts. map (( contact ) => (
< button
key = {contact.id}
onClick = {() => setSelected (contact.id)}
className = { cn (
"flex flex-col items-center gap-1.5 p-2 rounded-md transition-colors" ,
selected === contact.id
? "bg-primary/5"
: "hover:bg-muted"
)}
>
< Avatar
className = { cn (
"h-10 w-10 border-2 transition-colors" ,
selected === contact.id
? "border-primary"
: "border-transparent"
)}
>
< AvatarFallback className = "text-xs" >
{contact.initials}
</ AvatarFallback >
</ Avatar >
< span className = "text-xs truncate w-full text-center" >
{contact.name}
</ span >
</ button >
))}
</ div >
</ div >
{ /* Amount input */ }
< div className = "space-y-2" >
< div className = "relative" >
< span className = "absolute left-3 top-1/2 -translate-y-1/2 text-xl text-muted-foreground" >
$
</ span >
< Input
type = "number"
value = {amount}
onChange = {( e ) => setAmount (e.target.value)}
placeholder = "0.00"
className = "pl-8 text-xl h-12 text-center"
step = "0.01"
/>
</ div >
< div className = "flex justify-center gap-2" >
{[ "25" , "50" , "100" ]. map (( preset ) => (
< Button
key = {preset}
variant = "outline"
size = "sm"
onClick = {() => setAmount (preset)}
className = "text-xs"
>
${preset}
</ Button >
))}
</ div >
</ div >
</ div >
< DialogFooter >
< Button variant = "outline" onClick = {handleClose}>
Cancel
</ Button >
< Button
onClick = {handleSend}
disabled = { ! selected || ! amount || sending}
>
{sending ? (
< Loader2 className = "h-4 w-4 animate-spin" />
) : (
<>
< Send className = "mr-2 h-4 w-4" />
Send
</>
)}
</ Button >
</ DialogFooter >
</>
)}
</ DialogContent >
</ Dialog >
);
}