{
  "name": "address-02-block",
  "type": "registry:block",
  "dependencies": [
    "@hookform/resolvers",
    "lucide-react",
    "react-hook-form",
    "zod"
  ],
  "registryDependencies": [
    "badge",
    "button",
    "card",
    "checkbox",
    "dialog",
    "form",
    "input",
    "https://ui.stackzero.co/r/phone-number-input-basic.json",
    "https://ui.stackzero.co/r/input-icon.json"
  ],
  "files": [
    {
      "type": "registry:block",
      "content": "\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { z } from \"zod\";\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n  Form,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormMessage,\n} from \"@/components/ui/form\";\nimport { Input } from \"@/components/ui/input\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Edit, MapPin, Phone, Mail, User } from \"lucide-react\";\nimport PhoneInput from \"@/components/commerce-ui/phone-number-input-basic\";\nimport { cn } from \"@/lib/utils\";\n\nexport const addressFormSchema = z.object({\n  address1: z.string().min(1, \"Address is required\"),\n  address2: z.string().optional(),\n  city: z.string().min(1, \"City is required\"),\n  country: z.string().min(1, \"Country is required\"),\n  email: z.string().email(\"Invalid email\").optional(),\n  firstName: z.string().min(1, \"First name is required\"),\n  isBillingAddress: z.boolean(),\n  lastName: z.string().min(1, \"Last name is required\"),\n  phone: z.string().optional(),\n  postalCode: z.string().min(1, \"Postal code is required\"),\n  state: z.string().min(1, \"State is required\"),\n});\n\nexport type AddressFormValues = z.infer<typeof addressFormSchema>;\n\nexport type AddressCardProps = {\n  value?: AddressFormValues;\n  onChange?: (value: AddressFormValues) => void;\n  onSubmit?: (value: AddressFormValues) => void;\n  title?: string;\n  editButtonLabel?: string;\n  saveButtonLabel?: string;\n  cancelButtonLabel?: string;\n  disabled?: boolean;\n  className?: string;\n  showBillingBadge?: boolean;\n};\n\nfunction Address_02({\n  className = \"\",\n  disabled = false,\n  onChange,\n  onSubmit,\n  title = \"Address\",\n  editButtonLabel = \"Edit\",\n  saveButtonLabel = \"Save Changes\",\n  cancelButtonLabel = \"Cancel\",\n  value,\n  showBillingBadge = true,\n}: AddressCardProps) {\n  const [isModalOpen, setIsModalOpen] = useState(false);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const form = useForm<AddressFormValues>({\n    defaultValues: value || {\n      address1: \"\",\n      address2: \"\",\n      city: \"\",\n      country: \"\",\n      email: \"\",\n      firstName: \"\",\n      isBillingAddress: false,\n      lastName: \"\",\n      phone: \"\",\n      postalCode: \"\",\n      state: \"\",\n    },\n    mode: \"onChange\",\n    resolver: zodResolver(addressFormSchema),\n  });\n\n  // Update form when value prop changes\n  useEffect(() => {\n    if (value) {\n      form.reset(value);\n    }\n  }, [value, form]);\n\n  // Watch form values for onChange callback\n  const watchedValues = form.watch();\n  useEffect(() => {\n    if (onChange && isModalOpen) {\n      onChange(watchedValues);\n    }\n  }, [watchedValues, onChange, isModalOpen]);\n\n  const handleSubmit = async (formData: AddressFormValues) => {\n    setIsLoading(true);\n    try {\n      await onSubmit?.(formData);\n      setIsModalOpen(false);\n    } catch (error) {\n      console.error(\"Error saving address:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const handleCancel = () => {\n    if (value) {\n      form.reset(value);\n    }\n    setIsModalOpen(false);\n  };\n\n  // Check if address has data\n  const hasAddressData =\n    value && (value.firstName || value.lastName || value.address1);\n\n  // Format address for display\n  const formatAddress = () => {\n    if (!value) return null;\n\n    const fullName = [value.firstName, value.lastName]\n      .filter(Boolean)\n      .join(\" \");\n    const address1 = value.address1;\n    const address2 = value.address2;\n    const cityStateZip = [value.city, value.state, value.postalCode]\n      .filter(Boolean)\n      .join(\", \");\n    const country = value.country;\n\n    return {\n      fullName,\n      address1,\n      address2,\n      cityStateZip,\n      country,\n      phone: value.phone,\n      email: value.email,\n    };\n  };\n\n  const addressDisplay = formatAddress();\n\n  return (\n    <Card className={cn(\"md:min-w-[400px]\", className)}>\n      <CardHeader className=\"flex flex-row flex-wrap items-center justify-between space-y-0 pb-4\">\n        <div className=\"flex items-center gap-2\">\n          <CardTitle className=\"text-lg font-semibold\">{title}</CardTitle>\n          {showBillingBadge && value?.isBillingAddress && (\n            <Badge variant=\"secondary\" className=\"text-xs\">\n              Billing Address\n            </Badge>\n          )}\n        </div>\n        <Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>\n          <DialogTrigger asChild>\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              disabled={disabled}\n              className=\"flex items-center gap-2\"\n            >\n              <Edit className=\"h-4 w-4\" />\n              {editButtonLabel}\n            </Button>\n          </DialogTrigger>\n          <DialogContent className=\"max-h-[90vh] max-w-2xl overflow-y-auto\">\n            <DialogHeader>\n              <DialogTitle>Edit {title}</DialogTitle>\n              <DialogDescription>\n                Update your address information below.\n              </DialogDescription>\n            </DialogHeader>\n\n            <Form {...form}>\n              <form\n                onSubmit={form.handleSubmit(handleSubmit)}\n                className=\"space-y-4\"\n              >\n                <div className=\"grid gap-4\">\n                  <div className=\"flex flex-wrap gap-4\">\n                    <div className=\"min-w-[180px] flex-1\">\n                      <FormField\n                        control={form.control}\n                        name=\"firstName\"\n                        render={({ field }) => (\n                          <FormItem>\n                            <FormLabel>First Name</FormLabel>\n                            <FormControl>\n                              <Input\n                                {...field}\n                                disabled={isLoading}\n                                autoComplete=\"given-name\"\n                                required\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n                    <div className=\"min-w-[180px] flex-1\">\n                      <FormField\n                        control={form.control}\n                        name=\"lastName\"\n                        render={({ field }) => (\n                          <FormItem>\n                            <FormLabel>Last Name</FormLabel>\n                            <FormControl>\n                              <Input\n                                {...field}\n                                disabled={isLoading}\n                                autoComplete=\"family-name\"\n                                required\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n                  </div>\n\n                  <FormField\n                    control={form.control}\n                    name=\"address1\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel>Address</FormLabel>\n                        <FormControl>\n                          <Input\n                            {...field}\n                            disabled={isLoading}\n                            autoComplete=\"address-line1\"\n                            required\n                          />\n                        </FormControl>\n                        <FormMessage />\n                      </FormItem>\n                    )}\n                  />\n\n                  <FormField\n                    control={form.control}\n                    name=\"address2\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel>Apartment, suite, etc. (optional)</FormLabel>\n                        <FormControl>\n                          <Input\n                            {...field}\n                            disabled={isLoading}\n                            autoComplete=\"address-line2\"\n                          />\n                        </FormControl>\n                        <FormMessage />\n                      </FormItem>\n                    )}\n                  />\n\n                  <div className=\"flex flex-wrap gap-4\">\n                    <div className=\"min-w-[120px] flex-1\">\n                      <FormField\n                        control={form.control}\n                        name=\"city\"\n                        render={({ field }) => (\n                          <FormItem>\n                            <FormLabel>City</FormLabel>\n                            <FormControl>\n                              <Input\n                                {...field}\n                                disabled={isLoading}\n                                autoComplete=\"address-level2\"\n                                required\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n                    <div className=\"min-w-[120px] flex-1\">\n                      <FormField\n                        control={form.control}\n                        name=\"state\"\n                        render={({ field }) => (\n                          <FormItem>\n                            <FormLabel>State</FormLabel>\n                            <FormControl>\n                              <Input\n                                {...field}\n                                disabled={isLoading}\n                                autoComplete=\"address-level1\"\n                                required\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n                    <div className=\"min-w-[120px] flex-1\">\n                      <FormField\n                        control={form.control}\n                        name=\"postalCode\"\n                        render={({ field }) => (\n                          <FormItem>\n                            <FormLabel>Postal Code</FormLabel>\n                            <FormControl>\n                              <Input\n                                {...field}\n                                disabled={isLoading}\n                                autoComplete=\"postal-code\"\n                                required\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n                  </div>\n\n                  <FormField\n                    control={form.control}\n                    name=\"country\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel>Country</FormLabel>\n                        <FormControl>\n                          <Input\n                            {...field}\n                            disabled={isLoading}\n                            autoComplete=\"country\"\n                            required\n                          />\n                        </FormControl>\n                        <FormMessage />\n                      </FormItem>\n                    )}\n                  />\n\n                  <FormField\n                    control={form.control}\n                    name=\"phone\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel>Phone (optional)</FormLabel>\n                        <FormControl>\n                          <PhoneInput\n                            {...field}\n                            disabled={isLoading}\n                            autoComplete=\"tel\"\n                            type=\"tel\"\n                          />\n                        </FormControl>\n                        <FormMessage />\n                      </FormItem>\n                    )}\n                  />\n\n                  <FormField\n                    control={form.control}\n                    name=\"email\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel>Email (optional)</FormLabel>\n                        <FormControl>\n                          <Input\n                            {...field}\n                            disabled={isLoading}\n                            autoComplete=\"email\"\n                            type=\"email\"\n                          />\n                        </FormControl>\n                        <FormMessage />\n                      </FormItem>\n                    )}\n                  />\n\n                  <FormField\n                    control={form.control}\n                    name=\"isBillingAddress\"\n                    render={({ field }) => (\n                      <FormItem className=\"flex flex-row items-start space-y-0 space-x-3\">\n                        <FormControl>\n                          <Checkbox\n                            checked={field.value ?? false}\n                            onCheckedChange={field.onChange}\n                            disabled={isLoading}\n                          />\n                        </FormControl>\n                        <div className=\"space-y-1 leading-none\">\n                          <FormLabel>Use as billing address</FormLabel>\n                        </div>\n                      </FormItem>\n                    )}\n                  />\n                </div>\n\n                <DialogFooter className=\"gap-2\">\n                  <Button\n                    type=\"button\"\n                    variant=\"outline\"\n                    onClick={handleCancel}\n                    disabled={isLoading}\n                  >\n                    {cancelButtonLabel}\n                  </Button>\n                  <Button type=\"submit\" disabled={isLoading}>\n                    {isLoading ? \"Saving...\" : saveButtonLabel}\n                  </Button>\n                </DialogFooter>\n              </form>\n            </Form>\n          </DialogContent>\n        </Dialog>\n      </CardHeader>\n\n      <CardContent>\n        {hasAddressData && addressDisplay ? (\n          <div className=\"space-y-3\">\n            {addressDisplay.fullName && (\n              <div className=\"flex items-center gap-2\">\n                <User className=\"text-muted-foreground h-4 w-4\" />\n                <span className=\"font-medium\">{addressDisplay.fullName}</span>\n              </div>\n            )}\n\n            <div className=\"flex items-start gap-2\">\n              <MapPin className=\"text-muted-foreground mt-0.5 h-4 w-4\" />\n              <div className=\"space-y-1 text-sm\">\n                {addressDisplay.address1 && (\n                  <div>{addressDisplay.address1}</div>\n                )}\n                {addressDisplay.address2 && (\n                  <div>{addressDisplay.address2}</div>\n                )}\n                {addressDisplay.cityStateZip && (\n                  <div>{addressDisplay.cityStateZip}</div>\n                )}\n                {addressDisplay.country && <div>{addressDisplay.country}</div>}\n              </div>\n            </div>\n\n            {addressDisplay.phone && (\n              <div className=\"flex items-center gap-2\">\n                <Phone className=\"text-muted-foreground h-4 w-4\" />\n                <span className=\"text-sm\">{addressDisplay.phone}</span>\n              </div>\n            )}\n\n            {addressDisplay.email && (\n              <div className=\"flex items-center gap-2\">\n                <Mail className=\"text-muted-foreground h-4 w-4\" />\n                <span className=\"text-sm\">{addressDisplay.email}</span>\n              </div>\n            )}\n          </div>\n        ) : (\n          <div className=\"text-muted-foreground py-8 text-center\">\n            <MapPin className=\"mx-auto mb-2 h-8 w-8 opacity-50\" />\n            <p className=\"text-sm\">No address information available</p>\n            <p className=\"text-xs\">\n              Click &quot;{editButtonLabel}&quot; to add an address\n            </p>\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n\nexport default Address_02;\n",
      "path": "/components/commerce-ui/blocks/address/address-02.tsx",
      "target": "components/commerce-ui/address-02.tsx"
    }
  ]
}