Skip to content

Commit

Permalink
Merge pull request #574 from commercelayer/fix/stripe-payments
Browse files Browse the repository at this point in the history
Update Order: Set customer address using the `invertAddresses` prop
  • Loading branch information
acasazza authored Aug 23, 2024
2 parents de9eeff + e444399 commit d16a9a4
Show file tree
Hide file tree
Showing 10 changed files with 2,986 additions and 6,237 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useNx": false,
"npmClient": "pnpm",
"version": "4.15.8",
"version": "4.15.9-beta.3",
"command": {
"version": {
"preid": "beta"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"devDependencies": {
"@commercelayer/eslint-config-ts-react": "^1.4.5",
"husky": "^9.0.11",
"husky": "^9.1.5",
"lerna": "^8.1.3",
"typescript": "^5.4.5"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/react-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@commercelayer/react-components",
"version": "4.15.8",
"version": "4.15.9-beta.3",
"description": "The Official Commerce Layer React Components",
"main": "lib/cjs/index.js",
"module": "lib/esm/index.js",
Expand Down Expand Up @@ -182,7 +182,7 @@
"@commercelayer/organization-config": "^1.4.8",
"@commercelayer/sdk": "6.11.0",
"@stripe/react-stripe-js": "^2.7.3",
"@stripe/stripe-js": "^4.1.0",
"@stripe/stripe-js": "^4.2.0",
"@tanstack/react-table": "^8.17.3",
"@types/iframe-resizer": "^3.5.13",
"axios": "^1.7.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import addressReducer, {
setAddressErrors,
type SetAddressParams,
setCloneAddress,
saveAddresses
saveAddresses,
ICustomerAddress
} from '#reducers/AddressReducer'
import { type BaseError } from '#typings/errors'
import OrderContext from '#context/OrderContext'
Expand Down Expand Up @@ -92,17 +93,18 @@ export function AddressesContainer(props: Props): JSX.Element {
setAddress: (params: SetAddressParams<AddressSchema>) => {
defaultAddressContext.setAddress({ ...params, dispatch })
},
saveAddresses: async (
customerEmail?: string
): ReturnType<typeof saveAddresses> =>
saveAddresses: async (params: {
customerEmail?: string,
customerAddress?: ICustomerAddress
}): ReturnType<typeof saveAddresses> =>
await saveAddresses({
config,
dispatch,
updateOrder,
order,
orderId,
state,
customerEmail
...params
}),
setCloneAddress: (id: string, resource: AddressResource): void => {
setCloneAddress(id, resource, dispatch)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export function SaveAddressesButton(props: Props): JSX.Element {
)
customerEmail = Object.keys(isValidEmail).length > 0
}

const shippingAddressCleaned: any = Object.keys(shippingAddress ?? {}).reduce(
(acc, key) => {
return {
Expand Down Expand Up @@ -103,12 +102,15 @@ export function SaveAddressesButton(props: Props): JSX.Element {
shippingAddressId,
lineItems: order?.line_items
})
// NOTE: This is a temporary fix to avoid the button to be disabled when the user is editing an address
const invertAddressesDisable = invertAddresses && shippingAddressId ? false : shippingDisable
const disable =
disabled ||
customerEmail ||
billingDisable ||
shippingDisable ||
invertAddressesDisable ||
countryLockDisable

const handleClick = async (): Promise<void> => {
if (errors && Object.keys(errors).length === 0 && !disable) {
let response: {
Expand All @@ -118,15 +120,29 @@ export function SaveAddressesButton(props: Props): JSX.Element {
success: false
}
setForceDisable(true)
if (order && saveAddresses != null) {
response = await saveAddresses(email)
} else if (createCustomerAddress && billingAddress) {
const address = { ...billingAddress }
if (addressId) address.id = addressId
void createCustomerAddress(address as TCustomerAddress)
response = {
success: true
}
switch (true) {
case order != null && addressId != null && createCustomerAddress != null && saveAddresses != null:
response = await saveAddresses({
customerEmail: email,
customerAddress: {
resource: invertAddresses ? 'shipping_address' : 'billing_address',
id: addressId
}
})
break;
case order != null && saveAddresses != null:
response = await saveAddresses({
customerEmail: email,
})
break;
case createCustomerAddress != null:
const address = invertAddresses ? { ...shippingAddress } : { ...billingAddress }
if (addressId) address.id = addressId
void createCustomerAddress(address as TCustomerAddress)
response = {
success: true
}
break;
}
setForceDisable(false)
if (onClick && response.success) onClick(response)
Expand Down
8 changes: 6 additions & 2 deletions packages/react-components/src/context/AddressContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import {
type AddressState,
setAddress,
type AddressResource,
type saveAddresses
type saveAddresses,
ICustomerAddress
} from '#reducers/AddressReducer'
import { type BaseError } from '#typings/errors'

type DefaultContext = {
saveAddresses?: (customerEmail?: string) => ReturnType<typeof saveAddresses>
saveAddresses?: (params: {
customerEmail?: string,
customerAddress?: ICustomerAddress
}) => ReturnType<typeof saveAddresses>
setCloneAddress: (id: string, resource: AddressResource) => void
setAddress: typeof setAddress
setAddressErrors: (errors: BaseError[], resource: AddressResource) => void
Expand Down
71 changes: 24 additions & 47 deletions packages/react-components/src/reducers/AddressReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { type updateOrder } from './OrderReducer'
import camelCase from 'lodash/camelCase'
import { type TCustomerAddress } from './CustomerReducer'
import { type TResourceError } from '#components/errors/Errors'
import { invertedAddressesHandler } from '#utils/addressesManager'
import { invertedAddressesHandler, sanitizeMetadataFields } from '#utils/addressesManager'
import { formCleaner } from '#utils/formCleaner'
import { type AddressValuesKeys } from '#context/BillingAddressFormContext'
import { type AddressInputName } from '#typings/index'
Expand Down Expand Up @@ -168,6 +168,11 @@ export const setCloneAddress: SetCloneAddress = (id, resource, dispatch) => {
})
}

export interface ICustomerAddress {
id: string | undefined
resource: AddressResource
}

interface TSaveAddressesParams {
orderId?: string
order?: Order | null
Expand All @@ -177,18 +182,20 @@ interface TSaveAddressesParams {
dispatch: Dispatch<AddressAction>
getCustomerAddresses?: () => Promise<void>
customerEmail?: string
customerAddress?: ICustomerAddress
}

export async function saveAddresses({
config,
updateOrder,
order,
state,
customerEmail
customerEmail,
customerAddress
}: TSaveAddressesParams): Promise<{
success: boolean
order?: Order
error?: unknown
error?: unknown,
}> {
const {
shipToDifferentAddress,
Expand All @@ -202,15 +209,17 @@ export async function saveAddresses({
const sdk = getSdk(config)
if (order) {
let orderAttributes: OrderUpdate | null = null
const billingAddressCloneId = customerAddress?.resource === 'billing_address' ? customerAddress?.id : billingAddressId
const shippingAddressCloneId = customerAddress?.resource === 'shipping_address' ? customerAddress?.id : shippingAddressId
if (invertAddresses) {
orderAttributes = await invertedAddressesHandler({
billingAddress,
billingAddressId,
billingAddressId: billingAddressCloneId,
customerEmail,
order,
shipToDifferentAddress,
shippingAddress,
shippingAddressId,
shippingAddressId: shippingAddressCloneId,
sdk
})
} else {
Expand All @@ -221,70 +230,38 @@ export async function saveAddresses({
const currentBillingAddressRef = order?.billing_address?.reference
orderAttributes = {
id: order?.id,
_billing_address_clone_id: billingAddressId,
_shipping_address_clone_id: billingAddressId,
_billing_address_clone_id: billingAddressCloneId,
_shipping_address_clone_id: billingAddressCloneId,
customer_email: customerEmail
}
if (currentBillingAddressRef === billingAddressId) {
if (currentBillingAddressRef === billingAddressCloneId) {
orderAttributes._billing_address_clone_id = order?.billing_address?.id
orderAttributes._shipping_address_clone_id =
order?.shipping_address?.id
}
if (billingAddress != null && Object.keys(billingAddress).length > 0) {
if (billingAddress != null && Object.keys(billingAddress).length > 0 && !billingAddressCloneId) {
delete orderAttributes._billing_address_clone_id
delete orderAttributes._shipping_address_clone_id
if (!doNotShipItems) {
orderAttributes._shipping_address_same_as_billing = true
}
const hasMetadata = Object.keys(billingAddress).filter((key) => {
if (key.startsWith('metadata_')) {
return true
}
return false
})
if (hasMetadata?.length > 0) {
hasMetadata.forEach((key) => {
const metadataKey = key.replace('metadata_', '')
billingAddress.metadata = {
...(billingAddress.metadata || {}),
[metadataKey]: billingAddress[key]
}
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete billingAddress[key]
})
}
const address = await sdk.addresses.create(billingAddress)
const billingAddressWithMeta = sanitizeMetadataFields(billingAddress)
const address = await sdk.addresses.create(billingAddressWithMeta)
orderAttributes.billing_address = sdk.addresses.relationship(
address.id
)
}
if (shipToDifferentAddress) {
delete orderAttributes._shipping_address_same_as_billing
if (shippingAddressId)
orderAttributes._shipping_address_clone_id = shippingAddressId
if (shippingAddressCloneId)
orderAttributes._shipping_address_clone_id = shippingAddressCloneId
if (
shippingAddress != null &&
Object.keys(shippingAddress).length > 0
) {
delete orderAttributes._shipping_address_clone_id
const hasMetadata = Object.keys(shippingAddress).filter((key) => {
if (key.startsWith('metadata_')) {
return true
}
return false
})
if (hasMetadata?.length > 0) {
hasMetadata.forEach((key) => {
const metadataKey = key.replace('metadata_', '')
shippingAddress.metadata = {
...(shippingAddress.metadata || {}),
[metadataKey]: shippingAddress[key]
}
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete shippingAddress[key]
})
}
const address = await sdk.addresses.create(shippingAddress)
const shippingAddressWithMeta = sanitizeMetadataFields(shippingAddress)
const address = await sdk.addresses.create(shippingAddressWithMeta)
orderAttributes.shipping_address = sdk.addresses.relationship(
address.id
)
Expand Down
7 changes: 5 additions & 2 deletions packages/react-components/src/reducers/CustomerReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type TriggerAttributeHelper,
triggerAttributeHelper
} from '#utils/triggerAttributeHelper'
import { sanitizeMetadataFields } from '#utils/addressesManager'

export type CustomerActionType =
| 'setErrors'
Expand Down Expand Up @@ -373,7 +374,8 @@ export async function createCustomerAddress({
const { id } = address
try {
if (id) {
const upAddress = await sdk.addresses.update(address)
const addressWithMeta = sanitizeMetadataFields(address) as AddressUpdate
const upAddress = await sdk.addresses.update(addressWithMeta)
const updatedAddresses = state?.addresses?.map((a) => {
if (a.id === upAddress.id) return upAddress
return a
Expand All @@ -385,7 +387,8 @@ export async function createCustomerAddress({
})
}
} else {
const newAddress = await sdk.addresses.create(address)
const addressWithMeta = sanitizeMetadataFields(address)
const newAddress = await sdk.addresses.create(addressWithMeta)
if (state?.customers?.id && newAddress?.id) {
// @ts-expect-error Expected customer_email
const newCustomerAddress = await sdk.customer_addresses.create({
Expand Down
22 changes: 21 additions & 1 deletion packages/react-components/src/utils/addressesManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export async function invertedAddressesHandler({
orderAttributes._billing_address_clone_id = order?.billing_address?.id
orderAttributes._shipping_address_clone_id = order?.shipping_address?.id
}
if (shippingAddress != null && Object.keys(shippingAddress).length > 0) {
if (shippingAddress != null && Object.keys(shippingAddress).length > 0 && !shippingAddressId) {
delete orderAttributes._billing_address_clone_id
delete orderAttributes._shipping_address_clone_id
orderAttributes._billing_address_same_as_shipping = true
Expand Down Expand Up @@ -340,3 +340,23 @@ export function addressesController({
shippingDisable
}
}

export function sanitizeMetadataFields(address: AddressCreate): AddressCreate {
const hasMetadata = Object.keys(address).filter((key) => {
if (key.startsWith('metadata_')) {
return true
}
return false
})
if (hasMetadata?.length > 0) {
hasMetadata.forEach((key) => {
const metadataKey = key.replace('metadata_', '')
address.metadata = {
...(address.metadata || {}),
[metadataKey]: address[key as keyof AddressCreate]
}
delete address[key as keyof AddressCreate]
})
}
return address
}
Loading

0 comments on commit d16a9a4

Please sign in to comment.