4
0
forked from crowetic/commerce

Custom checkout improvements (#590)

* Add context for storing checkout information

* Remove unused useState
This commit is contained in:
Gonzalo Pozzo 2021-12-06 18:45:54 -03:00 committed by GitHub
parent 950a7637a5
commit d65b2efe9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 7 deletions

View File

@ -22,7 +22,7 @@ interface Form extends HTMLFormElement {
country: HTMLSelectElement
}
const PaymentMethodView: FC = () => {
const ShippingView: FC = () => {
const { setSidebarView } = useUI()
const addAddress = useAddAddress()
@ -115,4 +115,4 @@ const PaymentMethodView: FC = () => {
)
}
export default PaymentMethodView
export default ShippingView

View File

@ -0,0 +1,111 @@
import React, {
FC,
useCallback,
useMemo,
useReducer,
useContext,
createContext,
} from 'react'
import type { CardFields } from '@commerce/types/customer/card'
import type { AddressFields } from '@commerce/types/customer/address'
export type State = {
cardFields: CardFields
addressFields: AddressFields
}
type CheckoutContextType = State & {
setCardFields: (cardFields: CardFields) => void
setAddressFields: (addressFields: AddressFields) => void
clearCheckoutFields: () => void
}
type Action =
| {
type: 'SET_CARD_FIELDS'
card: CardFields
}
| {
type: 'SET_ADDRESS_FIELDS'
address: AddressFields
}
| {
type: 'CLEAR_CHECKOUT_FIELDS'
}
const initialState: State = {
cardFields: {} as CardFields,
addressFields: {} as AddressFields,
}
export const CheckoutContext = createContext<State | any>(initialState)
CheckoutContext.displayName = 'CheckoutContext'
const checkoutReducer = (state: State, action: Action): State => {
switch (action.type) {
case 'SET_CARD_FIELDS':
return {
...state,
cardFields: action.card,
}
case 'SET_ADDRESS_FIELDS':
return {
...state,
addressFields: action.address,
}
case 'CLEAR_CHECKOUT_FIELDS':
return {
...state,
cardFields: initialState.cardFields,
addressFields: initialState.addressFields,
}
default:
return state
}
}
export const CheckoutProvider: FC = (props) => {
const [state, dispatch] = useReducer(checkoutReducer, initialState)
const setCardFields = useCallback(
(card: CardFields) => dispatch({ type: 'SET_CARD_FIELDS', card }),
[dispatch]
)
const setAddressFields = useCallback(
(address: AddressFields) =>
dispatch({ type: 'SET_ADDRESS_FIELDS', address }),
[dispatch]
)
const clearCheckoutFields = useCallback(
() => dispatch({ type: 'CLEAR_CHECKOUT_FIELDS' }),
[dispatch]
)
const cardFields = useMemo(() => state.cardFields, [state.cardFields])
const addressFields = useMemo(() => state.addressFields, [state.addressFields])
const value = useMemo(
() => ({
cardFields,
addressFields,
setCardFields,
setAddressFields,
clearCheckoutFields,
}),
[cardFields, addressFields, setCardFields, setAddressFields, clearCheckoutFields]
)
return <CheckoutContext.Provider value={value} {...props} />
}
export const useCheckoutContext = () => {
const context = useContext<CheckoutContextType>(CheckoutContext)
if (context === undefined) {
throw new Error(`useCheckoutContext must be used within a CheckoutProvider`)
}
return context
}

View File

@ -13,6 +13,7 @@ import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
import { Sidebar, Button, LoadingDots } from '@components/ui'
import PaymentMethodView from '@components/checkout/PaymentMethodView'
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
import { CheckoutProvider } from '@components/checkout/context'
import MenuSidebarView, { Link } from '../UserNav/MenuSidebarView'
import LoginView from '@components/auth/LoginView'
@ -120,7 +121,9 @@ const Layout: FC<Props> = ({
<main className="fit">{children}</main>
<Footer pages={pageProps.pages} />
<ModalUI />
<SidebarUI links={navBarlinks} />
<CheckoutProvider>
<SidebarUI links={navBarlinks} />
</CheckoutProvider>
<FeatureBar
title="This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy."
hide={acceptedCookies}

View File

@ -1,13 +1,13 @@
import type { UseSubmitCheckout } from '../checkout/use-submit-checkout'
import type { Address } from './customer/address'
import type { Card } from './customer/card'
import type { Address, AddressFields } from './customer/address'
import type { Card, CardFields } from './customer/card'
// Index
export type Checkout = any
export type CheckoutTypes = {
card?: Card
address?: Address
card?: Card | CardFields
address?: Address | AddressFields
checkout?: Checkout
hasPayment?: boolean
hasShipping?: boolean