import { select } from '@wordpress/data' export interface RibbitSessionBilling { first_name: string last_name: string email: string phone: string address_1: string address_2: string city: string state: string postcode: string country: string } type PartialBilling = Partial const BILLING_FIELDS: (keyof RibbitSessionBilling)[] = [ 'first_name', 'last_name', 'email', 'phone', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country', ] const trim = (value: unknown): string => (typeof value === 'string' ? value.trim() : '') const normalizeBilling = (partial: PartialBilling): RibbitSessionBilling => ({ first_name: trim(partial.first_name), last_name: trim(partial.last_name), email: trim(partial.email), phone: trim(partial.phone), address_1: trim(partial.address_1), address_2: trim(partial.address_2), city: trim(partial.city), state: trim(partial.state), postcode: trim(partial.postcode), country: trim(partial.country) || 'US', }) const mergeBillingSources = (...sources: PartialBilling[]): RibbitSessionBilling => { const merged: PartialBilling = {} for (const field of BILLING_FIELDS) { for (const source of sources) { const value = trim(source[field]) if (value && !merged[field]) { merged[field] = value } } } return normalizeBilling(merged) } const getCartStoreBilling = (): PartialBilling => { try { const cartStore = select('wc/store/cart') as | { getCustomerData?: () => { billingAddress?: PartialBilling shippingAddress?: PartialBilling } } | undefined if (!cartStore?.getCustomerData) { return {} } const customerData = cartStore.getCustomerData() const billingAddress = customerData?.billingAddress ?? {} const shippingAddress = customerData?.shippingAddress ?? {} const checkoutStore = select('wc/store/checkout') as | { getUseShippingAsBilling?: () => boolean } | undefined const useShippingAsBilling = checkoutStore?.getUseShippingAsBilling?.() ?? false if (useShippingAsBilling) { return mergeBillingSources(shippingAddress, billingAddress) } return mergeBillingSources(billingAddress, shippingAddress) } catch { return {} } } const getFieldFromDom = (names: string[], ids: string[]): string => { for (const name of names) { const byName = document.querySelector( `[name="${name}"]`, ) const value = trim(byName?.value) if (value) { return value } } for (const id of ids) { const byId = document.querySelector(`#${id}`) const value = trim(byId?.value) if (value) { return value } } return '' } const getDomBilling = (): PartialBilling => ({ first_name: getFieldFromDom( ['billing_first_name'], ['billing_first_name', 'billing-first_name'], ), last_name: getFieldFromDom(['billing_last_name'], ['billing_last_name', 'billing-last_name']), email: getFieldFromDom(['billing_email', 'email'], ['billing_email', 'billing-email', 'email']), phone: getFieldFromDom(['billing_phone', 'phone'], ['billing_phone', 'billing-phone', 'phone']), address_1: getFieldFromDom( ['billing_address_1'], ['billing_address_1', 'billing-address_1'], ), address_2: getFieldFromDom( ['billing_address_2'], ['billing_address_2', 'billing-address_2'], ), city: getFieldFromDom(['billing_city'], ['billing_city', 'billing-city']), state: getFieldFromDom(['billing_state'], ['billing_state', 'billing-state']), postcode: getFieldFromDom( ['billing_postcode'], ['billing_postcode', 'billing-postcode'], ), country: getFieldFromDom(['billing_country'], ['billing_country', 'billing-country']), }) export const getCheckoutBillingDetails = (): RibbitSessionBilling => mergeBillingSources(getCartStoreBilling(), getDomBilling()) export const ribbitSessionBillingToApiParams = ( billing: RibbitSessionBilling, ): Record => ({ FirstName: billing.first_name, LastName: billing.last_name, EmailAddress: billing.email, Phone: billing.phone, Address1: billing.address_1, Address2: billing.address_2, City: billing.city, State: billing.state, Zip: billing.postcode, Country: billing.country, }) export const appendRibbitSessionBillingToFormData = ( formData: FormData, billing: RibbitSessionBilling, ): void => { const params = ribbitSessionBillingToApiParams(billing) for (const [key, value] of Object.entries(params)) { formData.append(key, value) } }