BillingCustomerDataForm() — supabase Function Reference
Architecture documentation for the BillingCustomerDataForm() function in BillingCustomerDataForm.tsx from the supabase codebase.
Entity Profile
Relationship Graph
Source Code
apps/studio/components/interfaces/Organization/BillingSettings/BillingCustomerData/BillingCustomerDataForm.tsx lines 49–321
export const BillingCustomerDataForm = ({
form,
disabled = false,
className,
}: BillingCustomerDataFormProps) => {
const [showCountriesPopover, setShowCountriesPopover] = useState(false)
const [showTaxIDsPopover, setShowTaxIDsPopover] = useState(false)
const onSelectTaxIdType = (name: string) => {
const selectedTaxIdOption = TAX_IDS.find((option) => option.name === name)
if (!selectedTaxIdOption) return
form.setValue('tax_id_type', selectedTaxIdOption.type)
form.setValue('tax_id_value', '')
form.setValue('tax_id_name', name)
}
const onRemoveTaxId = () => {
form.setValue('tax_id_name', '', { shouldDirty: true })
form.setValue('tax_id_type', '', { shouldDirty: true })
form.setValue('tax_id_value', '', { shouldDirty: true })
}
const { tax_id_name, country } = form.watch()
const selectedTaxId = TAX_IDS.find((option) => option.name === tax_id_name)
const availableTaxIds = useMemo(() => {
return TAX_IDS.filter((taxId) => !country || taxId.countryIso2 === country).sort((a, b) =>
a.country.localeCompare(b.country)
)
}, [country])
return (
<div className={cn('flex flex-col space-y-4', className)}>
<FormField
control={form.control}
name="billing_name"
render={({ field }) => (
<FormItemLayout hideMessage label="Name">
<FormControl>
<Input {...field} disabled={disabled} />
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
<FormField
control={form.control}
name="line1"
render={({ field }) => (
<FormItemLayout hideMessage label="Address line 1">
<FormControl>
<Input {...field} placeholder="123 Main Street" disabled={disabled} />
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
<FormField
control={form.control}
name="line2"
render={({ field }) => (
<FormItemLayout hideMessage label="Address line 2 (optional)">
<FormControl>
<Input
{...field}
placeholder="Apartment, suite, unit, building, floor, etc."
disabled={disabled}
/>
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="country"
render={({ field }) => (
<FormItemLayout hideMessage label="Country">
<Popover open={showCountriesPopover} onOpenChange={setShowCountriesPopover}>
<PopoverTrigger asChild>
<FormControl>
<Button
type="default"
role="combobox"
size="medium"
disabled={disabled}
className={cn(
'w-full justify-between h-[34px]',
!field.value && 'text-muted'
)}
iconRight={
<ChevronsUpDown
className="ml-2 h-4 w-4 shrink-0 opacity-50"
strokeWidth={1.5}
/>
}
>
{field.value
? COUNTRIES.find((country) => country.code === field.value)?.name ||
'Select country'
: 'Select country'}
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent sameWidthAsTrigger className="p-0" align="start">
<Command>
<CommandInput placeholder="Search country..." />
<CommandList>
<CommandEmpty>No country found.</CommandEmpty>
<CommandGroup>
{COUNTRIES.map((country) => (
<CommandItem
key={country.code}
value={country.name}
onSelect={() => {
form.setValue('country', country.code, {
shouldDirty: true,
shouldTouch: true,
shouldValidate: true,
})
setShowCountriesPopover(false)
}}
>
<Check
className={cn(
'mr-2 h-4 w-4',
field.value === country.code ? 'opacity-100' : 'opacity-0'
)}
/>
{country.name}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItemLayout>
)}
/>
<FormField
control={form.control}
name="postal_code"
render={({ field }) => (
<FormItemLayout hideMessage label="Postal code">
<FormControl>
<Input {...field} placeholder="12345" disabled={disabled} />
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="city"
render={({ field }) => (
<FormItemLayout hideMessage label="City">
<FormControl>
<Input {...field} disabled={disabled} />
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
<FormField
control={form.control}
name="state"
render={({ field }) => (
<FormItemLayout hideMessage label="State / Province">
<FormControl>
<Input {...field} disabled={disabled} />
</FormControl>
<FormMessage />
</FormItemLayout>
)}
/>
</div>
<div className="grid grid-cols-2 gap-x-2 w-full items-end">
<FormField
name="tax_id_name"
control={form.control}
render={() => (
<FormItemLayout hideMessage layout="vertical" label="Tax ID">
<Popover open={showTaxIDsPopover} onOpenChange={setShowTaxIDsPopover}>
<PopoverTrigger asChild>
<FormControl>
<Button
type="default"
role="combobox"
size="medium"
disabled={disabled}
className={cn(
'w-full justify-between h-[34px] pr-2',
!selectedTaxId && 'text-muted'
)}
iconRight={
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50" strokeWidth={1.5} />
}
>
{selectedTaxId
? `${selectedTaxId.country} - ${selectedTaxId.name}`
: 'Select tax ID'}
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent sameWidthAsTrigger className="p-0" align="start">
<Command>
<CommandInput placeholder="Search tax ID..." />
<CommandList>
<CommandEmpty>No tax ID found.</CommandEmpty>
<CommandGroup>
{availableTaxIds.map((option) => (
<CommandItem
key={option.name}
value={`${option.country} - ${option.name}`}
onSelect={() => {
onSelectTaxIdType(option.name)
setShowTaxIDsPopover(false)
}}
>
<Check
className={cn(
'mr-2 h-4 w-4',
selectedTaxId?.name === option.name ? 'opacity-100' : 'opacity-0'
)}
/>
{option.country} - {option.name}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItemLayout>
)}
/>
{selectedTaxId && (
<div className="flex items-center space-x-2 [&>div]:w-full">
<FormField
name="tax_id_value"
control={form.control}
render={({ field }) => (
<FormItemLayout hideMessage>
<FormControl>
<Input
{...field}
disabled={disabled}
placeholder={selectedTaxId?.placeholder}
/>
</FormControl>
</FormItemLayout>
)}
/>
<Button type="text" className="px-1" icon={<X />} onClick={() => onRemoveTaxId()} />
</div>
)}
</div>
</div>
)
}
Domain
Subdomains
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free