diff --git a/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx b/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx index 3710afb8300..6fd104901f4 100644 --- a/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx @@ -85,12 +85,16 @@ export const NewPaymentMethodElement = forwardRef( currentAddress, currentTaxId, customerName, + onAddressChange, + onTaxIdChange, }: { email?: string | null | undefined readOnly: boolean currentAddress?: CustomerAddress | null currentTaxId?: CustomerTaxId | null customerName?: string | undefined + onAddressChange?: (address: CustomerAddress) => void + onTaxIdChange?: (taxId: CustomerTaxId | null) => void }, ref ) => { @@ -123,13 +127,25 @@ export const NewPaymentMethodElement = forwardRef( form.setValue('tax_id_name', name) } - const { tax_id_name } = form.watch() + const { tax_id_name, tax_id_value } = form.watch() const selectedTaxId = TAX_IDS.find((option) => option.name === tax_id_name) const [purchasingAsBusiness, setPurchasingAsBusiness] = useState(currentTaxId != null) const [stripeAddress, setStripeAddress] = useState< StripeAddressElementChangeEvent['value'] | undefined >(undefined) + useEffect(() => { + if (!onTaxIdChange) return + if (purchasingAsBusiness && selectedTaxId && tax_id_value) { + onTaxIdChange({ + country: getEffectiveTaxCountry(selectedTaxId), + type: selectedTaxId.type, + value: tax_id_value, + }) + } else { + onTaxIdChange(null) + } + }, [purchasingAsBusiness, selectedTaxId, tax_id_value, onTaxIdChange]) const availableTaxIds = useMemo(() => { const country = stripeAddress?.address.country || null @@ -272,7 +288,15 @@ export const NewPaymentMethodElement = forwardRef( options={addressOptions} // Force reload after changing purchasingAsBusiness setting, it seems like the element does not reload otherwise key={`address-elements-${purchasingAsBusiness}`} - onChange={(evt) => setStripeAddress(evt.value)} + onChange={(evt) => { + setStripeAddress(evt.value) + if (onAddressChange && evt.complete) { + onAddressChange({ + ...evt.value.address, + line2: evt.value.address.line2 || undefined, + }) + } + }} onReady={() => setFullyLoaded(true)} /> diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx index 4eb34ecbf72..caa483e390b 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx @@ -84,6 +84,7 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => { }) const [topUpModalVisible, setTopUpModalVisible] = useState(false) + const [useAsDefaultBillingAddress, setUseAsDefaultBillingAddress] = useState(true) const [paymentConfirmationLoading, setPaymentConfirmationLoading] = useState(false) const [captchaToken, setCaptchaToken] = useState(null) const [captchaRef, setCaptchaRef] = useState(null) @@ -281,6 +282,8 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => { onSelectPaymentMethod={(pm) => form.setValue('paymentMethod', pm)} selectedPaymentMethod={form.getValues('paymentMethod')} readOnly={executingTopUp || paymentConfirmationLoading} + useAsDefaultBillingAddress={useAsDefaultBillingAddress} + onUseAsDefaultBillingAddressChange={setUseAsDefaultBillingAddress} /> )} /> diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx index 3eccf239531..82a0122acfb 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx @@ -26,6 +26,7 @@ import { useOrganizationCustomerProfileQuery } from '@/data/organizations/organi import { useOrganizationPaymentMethodSetupIntent } from '@/data/organizations/organization-payment-method-setup-intent-mutation' import { useOrganizationPaymentMethodsQuery } from '@/data/organizations/organization-payment-methods-query' import { useOrganizationTaxIdQuery } from '@/data/organizations/organization-tax-id-query' +import type { CustomerAddress, CustomerTaxId } from '@/data/organizations/types' import { SetupIntentResponse } from '@/data/stripe/setup-intent-mutation' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' import { BASE_PATH, STRIPE_PUBLIC_KEY } from '@/lib/constants' @@ -37,6 +38,10 @@ export interface PaymentMethodSelectionProps { onSelectPaymentMethod: (id: string) => void layout?: 'vertical' | 'horizontal' readOnly: boolean + onAddressChange?: (address: CustomerAddress) => void + onTaxIdChange?: (taxId: CustomerTaxId | null) => void + useAsDefaultBillingAddress: boolean + onUseAsDefaultBillingAddressChange: (useAsDefault: boolean) => void } const PaymentMethodSelection = forwardRef(function PaymentMethodSelection( @@ -45,6 +50,10 @@ const PaymentMethodSelection = forwardRef(function PaymentMethodSelection( onSelectPaymentMethod, layout = 'vertical', readOnly, + onAddressChange, + onTaxIdChange, + useAsDefaultBillingAddress, + onUseAsDefaultBillingAddressChange, }: PaymentMethodSelectionProps, ref ) { @@ -53,7 +62,6 @@ const PaymentMethodSelection = forwardRef(function PaymentMethodSelection( const [captchaToken, setCaptchaToken] = useState(null) const [captchaRef, setCaptchaRef] = useState(null) const [setupIntent, setSetupIntent] = useState(undefined) - const [useAsDefaultBillingAddress, setUseAsDefaultBillingAddress] = useState(true) const { resolvedTheme } = useTheme() const paymentRef = useRef(null) const [setupNewPaymentMethod, setSetupNewPaymentMethod] = useState(null) @@ -281,6 +289,8 @@ const PaymentMethodSelection = forwardRef(function PaymentMethodSelection( customerName={customerProfile?.billing_name} currentAddress={customerProfile?.address} currentTaxId={taxId} + onAddressChange={onAddressChange} + onTaxIdChange={onTaxIdChange} /> @@ -290,7 +300,9 @@ const PaymentMethodSelection = forwardRef(function PaymentMethodSelection( setUseAsDefaultBillingAddress(!useAsDefaultBillingAddress)} + onCheckedChange={() => { + onUseAsDefaultBillingAddressChange(!useAsDefaultBillingAddress) + }} />