"use client";
import { useState } from "react";
import { MapPin, Check } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const countries = [
{ code: "US", name: "United States", postalLabel: "ZIP Code", stateLabel: "State" },
{ code: "CA", name: "Canada", postalLabel: "Postal Code", stateLabel: "Province" },
{ code: "GB", name: "United Kingdom", postalLabel: "Postcode", stateLabel: "County" },
{ code: "AU", name: "Australia", postalLabel: "Postcode", stateLabel: "State" },
{ code: "DE", name: "Germany", postalLabel: "Postleitzahl", stateLabel: "State" },
{ code: "FR", name: "France", postalLabel: "Code postal", stateLabel: "Region" },
];
const usStates = [
"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado",
"Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho",
"Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana",
"Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota",
"Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
"New Hampshire", "New Jersey", "New Mexico", "New York",
"North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon",
"Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
"West Virginia", "Wisconsin", "Wyoming",
];
export const title = "React Dialog Block Billing Address Form";
export default function DialogBillingAddress() {
const [open, setOpen] = useState(false);
const [saved, setSaved] = useState(false);
const [country, setCountry] = useState("US");
const [saveForFuture, setSaveForFuture] = useState(false);
const [formData, setFormData] = useState({
fullName: "",
company: "",
address1: "",
address2: "",
city: "",
state: "",
postalCode: "",
phone: "",
});
const selectedCountry = countries.find((c) => c.code === country);
const handleInputChange = (field: string, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};
const formatPostalCode = (value: string, countryCode: string) => {
if (countryCode === "US") {
const cleaned = value.replace(/\D/g, "");
if (cleaned.length <= 5) return cleaned;
return `${cleaned.slice(0, 5)}-${cleaned.slice(5, 9)}`;
}
if (countryCode === "CA") {
const cleaned = value.replace(/[^A-Za-z0-9]/g, "").toUpperCase();
if (cleaned.length <= 3) return cleaned;
return `${cleaned.slice(0, 3)} ${cleaned.slice(3, 6)}`;
}
return value;
};
const handlePostalCodeChange = (value: string) => {
const formatted = formatPostalCode(value, country);
handleInputChange("postalCode", formatted);
};
const handleSave = () => {
console.log({ ...formData, country, saveForFuture });
setSaved(true);
};
const handleClose = () => {
setOpen(false);
setTimeout(() => {
setSaved(false);
setFormData({
fullName: "",
company: "",
address1: "",
address2: "",
city: "",
state: "",
postalCode: "",
phone: "",
});
setCountry("US");
setSaveForFuture(false);
}, 200);
};
const isValid =
formData.fullName &&
formData.address1 &&
formData.city &&
formData.state &&
formData.postalCode;
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<MapPin className="mr-2 h-4 w-4" />
Add Billing Address
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-lg">
{saved ? (
<>
<DialogHeader className="text-center">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 mb-4">
<Check className="h-6 w-6 text-green-600" />
</div>
<DialogTitle>Address Saved</DialogTitle>
<DialogDescription>
Your billing address has been saved successfully.
{saveForFuture && " It will be available for future purchases."}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={handleClose} className="w-full">
Done
</Button>
</DialogFooter>
</>
) : (
<>
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<MapPin className="h-5 w-5" />
Billing Address
</DialogTitle>
<DialogDescription>
Enter your billing address for this purchase.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid gap-2">
<Label htmlFor="country">Country</Label>
<Select value={country} onValueChange={setCountry}>
<SelectTrigger id="country">
<SelectValue />
</SelectTrigger>
<SelectContent>
{countries.map((c) => (
<SelectItem key={c.code} value={c.code}>
{c.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid gap-2">
<Label htmlFor="fullName">Full Name *</Label>
<Input
id="fullName"
placeholder="John Smith"
value={formData.fullName}
onChange={(e) => handleInputChange("fullName", e.target.value)}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="company">Company (Optional)</Label>
<Input
id="company"
placeholder="Acme Inc."
value={formData.company}
onChange={(e) => handleInputChange("company", e.target.value)}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="address1">Address Line 1 *</Label>
<Input
id="address1"
placeholder="123 Main Street"
value={formData.address1}
onChange={(e) => handleInputChange("address1", e.target.value)}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="address2">Address Line 2 (Optional)</Label>
<Input
id="address2"
placeholder="Apt 4B"
value={formData.address2}
onChange={(e) => handleInputChange("address2", e.target.value)}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-2">
<Label htmlFor="city">City *</Label>
<Input
id="city"
placeholder="San Francisco"
value={formData.city}
onChange={(e) => handleInputChange("city", e.target.value)}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="state">{selectedCountry?.stateLabel} *</Label>
{country === "US" ? (
<Select
value={formData.state}
onValueChange={(value) => handleInputChange("state", value)}
>
<SelectTrigger id="state">
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent>
{usStates.map((state) => (
<SelectItem key={state} value={state}>
{state}
</SelectItem>
))}
</SelectContent>
</Select>
) : (
<Input
id="state"
placeholder={selectedCountry?.stateLabel}
value={formData.state}
onChange={(e) => handleInputChange("state", e.target.value)}
/>
)}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-2">
<Label htmlFor="postalCode">{selectedCountry?.postalLabel} *</Label>
<Input
id="postalCode"
placeholder={country === "US" ? "94102" : ""}
value={formData.postalCode}
onChange={(e) => handlePostalCodeChange(e.target.value)}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="phone">Phone (Optional)</Label>
<Input
id="phone"
type="tel"
placeholder="+1 (555) 000-0000"
value={formData.phone}
onChange={(e) => handleInputChange("phone", e.target.value)}
/>
</div>
</div>
<div className="flex items-center space-x-2 pt-2">
<Checkbox
id="saveForFuture"
checked={saveForFuture}
onCheckedChange={(checked) => setSaveForFuture(checked as boolean)}
/>
<Label
htmlFor="saveForFuture"
className="text-sm font-normal cursor-pointer"
>
Save this address for future purchases
</Label>
</div>
</div>
<DialogFooter className="gap-2 sm:gap-0">
<Button variant="outline" onClick={handleClose}>
Cancel
</Button>
<Button onClick={handleSave} disabled={!isValid}>
Save Address
</Button>
</DialogFooter>
</>
)}
</DialogContent>
</Dialog>
);
}