Skip to content

Commit

Permalink
perf: Set attribute field to errors handler
Browse files Browse the repository at this point in the history
  • Loading branch information
acasazza committed Mar 28, 2022
1 parent 1083750 commit 0f60a39
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 70 deletions.
8 changes: 6 additions & 2 deletions src/components/Errors.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FunctionComponent, useContext, Fragment, useMemo } from 'react'
import React, { useContext, Fragment, useMemo } from 'react'
import Parent from './utils/Parent'
import GiftCardContext from '#context/GiftCardContext'
import OrderContext from '#context/OrderContext'
Expand All @@ -11,20 +11,22 @@ import components from '#config/components'
import CustomerContext from '#context/CustomerContext'
import PaymentMethodContext from '#context/PaymentMethodContext'
import PaymentMethodChildrenContext from '#context/PaymentMethodChildrenContext'
import ShipmentContext from '#context/ShipmentContext'

const propTypes = components.Errors.propTypes
const displayName = components.Errors.displayName

export type ErrorsProps = ErrorComponentProps & JSX.IntrinsicElements['span']

const Errors: FunctionComponent<ErrorsProps> = (props) => {
const Errors: React.FunctionComponent<ErrorsProps> = (props) => {
const { children, messages = [], resource, field, ...p } = props
const { payment } = useContext(PaymentMethodChildrenContext)
const { errors: orderErrors } = useContext(OrderContext)
const { errors: giftCardErrors } = useContext(GiftCardContext)
const { errors: lineItemErrors } = useContext(LineItemContext)
const { errors: addressErrors } = useContext(AddressContext)
const { errors: customerErrors } = useContext(CustomerContext)
const { errors: shipmentErrors } = useContext(ShipmentContext)
const {
errors: paymentMethodErrors,
currentPaymentMethodType,
Expand All @@ -38,6 +40,7 @@ const Errors: FunctionComponent<ErrorsProps> = (props) => {
...(lineItemErrors || []),
...(addressErrors || []),
...(customerErrors || []),
...(shipmentErrors || []),
...(paymentMethodErrors?.filter(
(v) =>
v.field === currentPaymentMethodType &&
Expand All @@ -50,6 +53,7 @@ const Errors: FunctionComponent<ErrorsProps> = (props) => {
lineItemErrors,
addressErrors,
customerErrors,
shipmentErrors,
paymentMethodErrors,
]
)
Expand Down
15 changes: 13 additions & 2 deletions src/components/PaymentSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PaymentResource } from '#reducers/PaymentMethodReducer'
import { LoaderType } from '#typings/index'
import { CustomerCardsTemplateChildren } from './utils/PaymentCardsTemplate'
import getCardDetails from '../utils/getCardDetails'
import OrderContext from '#context/OrderContext'

const propTypes = components.PaymentSource.propTypes
const displayName = components.PaymentSource.displayName
Expand All @@ -38,6 +39,7 @@ export type PaymentSourceProps = {
const PaymentSource: FunctionComponent<PaymentSourceProps> = (props) => {
const { readonly } = props
const { payment } = useContext(PaymentMethodChildrenContext)
const { order } = useContext(OrderContext)
const { payments } = useContext(CustomerContext)
const { currentPaymentMethodId, paymentSource, destroyPaymentSource } =
useContext(PaymentMethodContext)
Expand All @@ -52,15 +54,24 @@ const PaymentSource: FunctionComponent<PaymentSourceProps> = (props) => {
setShow(true)
const card = getCardDetails({
paymentType: payment?.payment_source_type as PaymentResource,
customerPayment: { payment_source: paymentSource },
customerPayment: {
payment_source: order?.payment_source || paymentSource,
},
})
if (card.brand) setShowCard(true)
} else setShow(false)
return () => {
setShow(false)
setShowCard(false)
}
}, [currentPaymentMethodId, paymentSource, payments, payment, readonly])
}, [
currentPaymentMethodId,
paymentSource,
payments,
payment,
readonly,
order,
])
const handleEditClick = async (e: MouseEvent) => {
e.stopPropagation()
paymentSource &&
Expand Down
11 changes: 10 additions & 1 deletion src/components/PlaceOrderContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const PlaceOrderContainer: FunctionComponent<PlaceOrderContainerProps> = (
)
const {
order,
setOrder,
setOrderErrors,
include,
addResourceToInclude,
Expand Down Expand Up @@ -95,7 +96,15 @@ const PlaceOrderContainer: FunctionComponent<PlaceOrderContainerProps> = (
const contextValue = {
...state,
setPlaceOrder: ({ paymentSource }: { paymentSource?: PaymentSourceType }) =>
setPlaceOrder({ config, order, state, setOrderErrors, paymentSource }),
setPlaceOrder({
config,
order,
state,
setOrderErrors,
paymentSource,
include,
setOrder,
}),
placeOrderPermitted: () =>
placeOrderPermitted({
config,
Expand Down
3 changes: 1 addition & 2 deletions src/components/Shipment.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, {
FunctionComponent,
Fragment,
useContext,
ReactNode,
Expand All @@ -21,7 +20,7 @@ type ShipmentProps = {
loader?: LoaderType
}

const Shipment: FunctionComponent<ShipmentProps> = ({
const Shipment: React.FunctionComponent<ShipmentProps> = ({
children,
loader = 'Loading...',
}) => {
Expand Down
111 changes: 55 additions & 56 deletions src/components/ShipmentsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import ShipmentContext, {
defaultShipmentContext,
} from '#context/ShipmentContext'
import React, {
FunctionComponent,
ReactNode,
useContext,
useEffect,
useReducer,
} from 'react'
import React, { ReactNode, useContext, useEffect, useReducer } from 'react'
import shipmentReducer, {
shipmentInitialState,
setShipmentErrors,
getShipments,
setShippingMethod,
} from '#reducers/ShipmentReducer'
Expand All @@ -18,30 +13,21 @@ import CommerceLayerContext from '#context/CommerceLayerContext'
import components from '#config/components'
import { BaseError } from '#typings/errors'
import { isEmpty } from 'lodash'
import Parent from './utils/Parent'
import { FunctionChildren } from '#typings'

const propTypes = components.ShipmentsContainer.propTypes
const displayName = components.ShipmentsContainer.displayName

type ShipmentsContainerChildrenProps = FunctionChildren<
Omit<ShipmentsContainerProps, 'children'> & {
errors: BaseError[]
}
>

type ShipmentsContainerProps = {
children: ShipmentsContainerChildrenProps
children: ReactNode
}
const ShipmentsContainer: FunctionComponent<ShipmentsContainerProps> = (
const ShipmentsContainer: React.FunctionComponent<ShipmentsContainerProps> = (
props
) => {
const { children, ...p } = props
const [state, dispatch] = useReducer(shipmentReducer, shipmentInitialState)
const { order, getOrder, include, addResourceToInclude, includeLoaded } =
useContext(OrderContext)
const config = useContext(CommerceLayerContext)
const errors: BaseError[] = []
useEffect(() => {
if (!include?.includes('shipments.available_shipping_methods')) {
addResourceToInclude({
Expand Down Expand Up @@ -75,49 +61,62 @@ const ShipmentsContainer: FunctionComponent<ShipmentsContainerProps> = (
},
})
}

if (order && order.shipments && order.shipments.length > 0) {
const hasShippingMethods = order.shipments.map((shipment) => {
return (
shipment.available_shipping_methods &&
shipment.available_shipping_methods.length > 0
)
})
if (hasShippingMethods.includes(false)) {
errors.push({
code: 'NO_SHIPPING_METHODS',
message: 'No shipping methods',
resource: 'shipments',
if (order && !isEmpty(config) && order.shipments) {
getShipments({ order, dispatch, config })
}
}, [order, include, includeLoaded])
useEffect(() => {
if (order) {
if (order.shipments && order.shipments.length > 0) {
const hasShippingMethods = order.shipments.map((shipment) => {
return (
shipment.available_shipping_methods &&
shipment.available_shipping_methods.length > 0
)
})
if (hasShippingMethods.includes(false)) {
setShipmentErrors(
[
...(state.errors || []),
{
code: 'NO_SHIPPING_METHODS',
message: 'No shipping methods',
resource: 'shipments',
},
],
dispatch
)
}
}
}
if (order && order.line_items && order.line_items.length > 0) {
const hasStocks = order.line_items.map((line_item) => {
return (
if (order.line_items && order.line_items.length > 0) {
const hasStocks = order.line_items.map((line_item) => {
// @ts-ignore
line_item.item?.do_not_ship || line_item.item?.inventory?.available
)
})
if (hasStocks.includes(false)) {
errors.push({
code: 'OUT_OF_STOCK',
message: 'No stock available',
resource: 'line_items',
return !(line_item.item?.inventory?.quantity >= line_item?.quantity)
? false
: // @ts-ignore
line_item.item?.do_not_ship ||
// @ts-ignore
line_item.item?.inventory?.available
})
if (hasStocks.includes(false)) {
setShipmentErrors(
[
...(state.errors || []),
{
code: 'OUT_OF_STOCK',
message: 'No stock available',
resource: 'line_items',
},
],
dispatch
)
}
}
}
if (errors.length > 0) {
dispatch({
type: 'setErrors',
payload: {
errors,
},
})
}
if (order && !isEmpty(config) && order.shipments) {
getShipments({ order, dispatch, config })
return () => {
setShipmentErrors([], dispatch)
}
}, [order, include, includeLoaded])
}, [order])
const contextValue = {
...state,
setShipmentErrors: (errors: BaseError[]) =>
Expand All @@ -132,14 +131,14 @@ const ShipmentsContainer: FunctionComponent<ShipmentsContainerProps> = (
}),
}

const parentProps = { ...p, errors: state.errors }
return (
<ShipmentContext.Provider value={contextValue}>
<Parent {...parentProps}>{children}</Parent>
{children}
</ShipmentContext.Provider>
)
}

ShipmentsContainer.propTypes = propTypes
ShipmentsContainer.displayName = displayName

export default ShipmentsContainer
1 change: 1 addition & 0 deletions src/components/utils/PriceTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const PriceTemplate: React.FunctionComponent<PTemplateProps> = (props) => {
formattedAmount,
...p
} = props
delete p.skuCode
return (
<>
<span className={className} {...p}>
Expand Down
2 changes: 1 addition & 1 deletion src/config/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ const components = {
},
ShipmentsContainer: {
displayName: 'ShipmentsContainer',
permittedChildren: ['Shipment', 'ReactNode'],
permittedChildren: ['Shipment', 'ReactNode', 'Errors'],
propTypes: {
children: childrenTypes.isRequired,
},
Expand Down
5 changes: 5 additions & 0 deletions src/context/OrderContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createContext } from 'react'
import { Order } from '@commercelayer/sdk'
import {
addToCart,
AddToCart,
Expand Down Expand Up @@ -26,6 +27,7 @@ type DefaultContext = {
addResourceToInclude: typeof addResourceToInclude
getOrder: getOrderContext
updateOrder: typeof updateOrder
setOrder: (order: Order) => void
} & OrderState

export const defaultOrderContext = {
Expand All @@ -34,6 +36,9 @@ export const defaultOrderContext = {
setOrderErrors: () => {
return
},
setOrder: () => {
return
},
setGiftCardOrCouponCode,
removeGiftCardOrCouponCode,
saveAddressToCustomerAddressBook,
Expand Down
4 changes: 2 additions & 2 deletions src/reducers/OrderReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ export const setGiftCardOrCouponCode: SetGiftCardOrCouponCode = async ({
}
return { success: false }
} catch (error: any) {
const errors = getErrors(error, 'gift_card_or_coupon_code')
const errors = getErrors(error, 'orders', codeType)
dispatch && setOrderErrors({ errors, dispatch })
return { success: false }
}
Expand Down Expand Up @@ -548,7 +548,7 @@ export const removeGiftCardOrCouponCode: RemoveGiftCardOrCouponCode = async ({
}
return { success: false }
} catch (error: any) {
const errors = getErrors(error, 'gift_card_or_coupon_code')
const errors = getErrors(error, 'orders', codeType)
console.error('Remove gift card o coupon code', errors)
dispatch && setOrderErrors({ errors, dispatch })
return { success: false }
Expand Down
4 changes: 2 additions & 2 deletions src/reducers/PaymentMethodReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export const setPaymentMethod: SetPaymentMethod = async ({
setOrderErrors && setOrderErrors([])
}
} catch (error) {
const errors = getErrors(error, 'orders')
const errors = getErrors(error, 'orders', paymentResource)
console.error('Set payment method', errors)
}
}
Expand Down Expand Up @@ -316,7 +316,7 @@ export const setPaymentSource: SetPaymentSource = async ({
}
}
} catch (error: any) {
const errors = getErrors(error, 'payment_methods')
const errors = getErrors(error, 'payment_methods', paymentResource)
console.error('Set payment source:', errors)
if (dispatch)
setErrors({
Expand Down
5 changes: 3 additions & 2 deletions src/utils/getErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { Dispatch } from 'react'

export default function getErrors(
error: any,
resource: ResourceErrorType
resource: ResourceErrorType,
field?: string
): BaseError[] {
return error?.errors?.map((e: any) => {
return { ...e, resource }
return { ...e, resource, ...(field && { field }) }
})
}

Expand Down

0 comments on commit 0f60a39

Please sign in to comment.