"use client" ;
import { useState } from "react" ;
import { ShoppingCart, Minus, Plus, 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" ;
const PRICE = 29.99 ;
const MAX_QTY = 99 ;
export const title = "React Dialog Block Select Quantity" ;
export default function DialogSelectQuantity () {
const [ open , setOpen ] = useState ( false );
const [ quantity , setQuantity ] = useState ( 1 );
const [ isUpdating , setIsUpdating ] = useState ( false );
const total = ( PRICE * quantity). toFixed ( 2 );
const handleChange = ( value : string ) => {
const num = parseInt (value, 10 );
if ( isNaN (num) || num < 1 ) {
setQuantity ( 1 );
} else if (num > MAX_QTY ) {
setQuantity ( MAX_QTY );
} else {
setQuantity (num);
}
};
const handleUpdate = async () => {
setIsUpdating ( true );
await new Promise (( resolve ) => setTimeout (resolve, 1000 ));
setIsUpdating ( false );
setOpen ( false );
};
return (
< Dialog open = {open} onOpenChange = {setOpen}>
< div className = "flex min-h-[350px] items-center justify-center" >
< DialogTrigger asChild >
< Button variant = "outline" >
< ShoppingCart className = "mr-2 h-4 w-4" />
Select Quantity
</ Button >
</ DialogTrigger >
</ div >
< DialogContent className = "sm:max-w-sm" >
< DialogHeader >
< DialogTitle >Select Quantity</ DialogTitle >
< DialogDescription >
Choose how many items you'd like.
</ DialogDescription >
</ DialogHeader >
< div className = "space-y-4 py-4" >
< div className = "flex items-center justify-center gap-3" >
< Button
variant = "outline"
size = "icon"
onClick = {() => setQuantity (( q ) => Math. max ( 1 , q - 1 ))}
disabled = {quantity <= 1 }
>
< Minus className = "h-4 w-4" />
</ Button >
< Input
type = "number"
value = {quantity}
onChange = {( e ) => handleChange (e.target.value)}
className = "w-20 text-center text-lg font-semibold"
min = { 1 }
max = { MAX_QTY }
/>
< Button
variant = "outline"
size = "icon"
onClick = {() => setQuantity (( q ) => Math. min ( MAX_QTY , q + 1 ))}
disabled = {quantity >= MAX_QTY }
>
< Plus className = "h-4 w-4" />
</ Button >
</ div >
< div className = "flex items-center justify-between rounded-lg border p-3" >
< div >
< p className = "text-sm font-medium" >${ PRICE } each</ p >
< p className = "text-xs text-muted-foreground" >{quantity} item{quantity > 1 ? "s" : "" }</ p >
</ div >
< p className = "text-lg font-semibold" >${total}</ p >
</ div >
</ div >
< DialogFooter >
< Button variant = "outline" onClick = {() => setOpen ( false )}>
Cancel
</ Button >
< Button onClick = {handleUpdate} disabled = {isUpdating}>
{isUpdating ? (
<>
< Loader2 className = "mr-2 h-4 w-4 animate-spin" />
Updating...
</>
) : (
"Update"
)}
</ Button >
</ DialogFooter >
</ DialogContent >
</ Dialog >
);
}