feat: useGetActiveOrderForCheckout

:%s
This commit is contained in:
lytrankieio123
2021-10-21 09:47:45 +07:00
parent aba0e43b93
commit bcdbea4059
12 changed files with 241 additions and 48 deletions

View File

@@ -1,5 +1,5 @@
import { Shipping } from 'src/components/icons';
import type { Discount, Measurement, Image } from './common'
import { ShippingMethod } from '@framework/schema';
import type { Discount, Image, Measurement } from './common';
export type SelectedOption = {
// The option's id.
@@ -60,6 +60,31 @@ export type ProductVariant = {
// Shopping cart, a.k.a Checkout
export type Cart = {
id: string
// ID of the customer to which the cart belongs.
customerId?: string
// The email assigned to this cart
email?: string
// The date and time when the cart was created.
createdAt: string
// The currency used for this cart
currency: { code: string }
// Specifies if taxes are included in the line items.
taxesIncluded: boolean
lineItems: LineItem[]
// The sum of all the prices of all the items in the cart.
// Duties, taxes, shipping and discounts excluded.
lineItemsSubtotalPrice: number
// Price of the cart before duties, shipping and taxes.
subtotalPrice: number
// The sum of all the prices of all the items in the cart.
// Duties, taxes and discounts included.
totalPrice: number
// Discounts that have been applied on the cart.
discounts?: Discount[]
}
export type CartCheckout = {
id: string
// ID of the customer to which the cart belongs.
customerId?: string
@@ -97,6 +122,10 @@ export type Cart = {
// Discounts that have been applied on the cart.
discounts?: Discount[]
totalDiscount: number
shippingLine: {
priceWithTax: number
shippingMethod: ShippingMethod
}
}
/**

View File

@@ -3066,6 +3066,11 @@ export type CartFragment = { __typename?: 'Order' } & Pick<
{ __typename?: 'Discount' } & Pick<Discount, 'type' | 'description' | 'amount' | 'amountWithTax'>
>
customer?: Maybe<{ __typename?: 'Customer' } & Pick<Customer, 'id' | 'firstName' | 'lastName' | 'emailAddress'>>
shippingLines: Array<
Pick<ShippingLine, 'priceWithTax'> & {
shippingMethod: Pick<ShippingMethod, 'id' | 'code' | 'name' | 'description'>;
}
>
lines: Array<
{ __typename?: 'OrderLine' } & Pick<
OrderLine,

View File

@@ -9,25 +9,8 @@ export const cartFragment = /* GraphQL */ `
total
totalWithTax
currencyCode
discounts {
type
description
amount
amountWithTax
}
customer {
id
firstName
lastName
emailAddress
}
shippingAddress {
streetLine1
city
province
postalCode
countryCode
phoneNumber
}
lines {
id

View File

@@ -1,6 +1,6 @@
import { Cart } from '@commerce/types/cart'
import { ProductCard, Product } from '@commerce/types/product'
import { CartFragment, SearchResultFragment, Favorite } from '../schema'
import { Cart, CartCheckout } from '@commerce/types/cart'
import { Product, ProductCard } from '@commerce/types/product'
import { CartFragment, Favorite, SearchResultFragment, ShippingMethod } from '../schema'
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
return {
@@ -36,6 +36,41 @@ export function normalizeFavoriteProductResult(item: Favorite) {
export function normalizeCart(order: CartFragment): Cart {
return {
id: order.id.toString(),
createdAt: order.createdAt,
taxesIncluded: true,
lineItemsSubtotalPrice: order.subTotalWithTax / 100,
currency: { code: order.currencyCode },
subtotalPrice: order.subTotalWithTax / 100,
totalPrice: order.totalWithTax / 100,
customerId: order.customer?.id,
lineItems: order.lines?.map((l) => ({
id: l.id,
name: l.productVariant.name,
quantity: l.quantity,
slug: l.productVariant.product.slug,
variantId: l.productVariant.id,
productId: l.productVariant.productId,
images: [{ url: l.featuredAsset?.preview + '?preset=thumb' || '' }],
discounts: l.discounts.map((d) => ({ value: d.amount / 100 })),
path: '',
variant: {
id: l.productVariant.id,
name: l.productVariant.name,
sku: l.productVariant.sku,
price: l.discountedUnitPriceWithTax / 100,
listPrice: l.unitPriceWithTax / 100,
image: {
url: l.featuredAsset?.preview + '?preset=thumb' || '',
},
requiresShipping: true,
},
})),
}
}
export function normalizeCartForCheckout(order: CartFragment): CartCheckout {
return {
id: order.id.toString(),
createdAt: order.createdAt,
@@ -59,6 +94,10 @@ export function normalizeCart(order: CartFragment): Cart {
countryCode: order.shippingAddress?.countryCode || '',
phoneNumber: order.shippingAddress?.phoneNumber || '',
},
shippingLine: {
priceWithTax: order.shippingLines[0].priceWithTax,
shippingMethod: order.shippingLines[0].shippingMethod as ShippingMethod
},
totalDiscount: order.discounts?.reduce((total, item) => total + item.amountWithTax, 0) / 100 || 0,
discounts: order.discounts.map(item => {
return { value: item.amountWithTax, description: item.description }

View File

@@ -0,0 +1,116 @@
export const getActiveOrderForCheckoutQuery = /* GraphQL */ `
query getActiveOrderForCheckout {
activeOrder {
...Cart
shippingAddress {
...OrderAddress
__typename
}
__typename
}
}
fragment Cart on Order {
id
code
state
active
customer {
id
firstName
lastName
emailAddress
}
lines {
id
featuredAsset {
...Asset
__typename
}
unitPrice
unitPriceWithTax
quantity
linePriceWithTax
discountedLinePriceWithTax
unitPriceWithTax
discountedUnitPriceWithTax
productVariant {
id
name
price
priceWithTax
stockLevel
productId
product {
slug
}
__typename
}
discounts {
amount
amountWithTax
description
adjustmentSource
type
__typename
}
__typename
}
totalQuantity
subTotal
subTotalWithTax
total
totalWithTax
shipping
shippingWithTax
currencyCode
shippingLines {
priceWithTax
shippingMethod {
id
code
name
description
__typename
}
__typename
}
discounts {
amount
amountWithTax
description
adjustmentSource
type
__typename
}
__typename
}
fragment Asset on Asset {
id
width
height
name
preview
focalPoint {
x
y
__typename
}
__typename
}
fragment OrderAddress on OrderAddress {
fullName
company
streetLine1
streetLine2
city
province
postalCode
country
phoneNumber
__typename
}
`

View File

@@ -1,11 +1,10 @@
import { RemoveOrderLineMutation, RemoveOrderLineMutationVariables } from '@framework/schema'
import { removeOrderLineMutation } from '@framework/utils/mutations/remove-order-line-mutation'
import { useState } from 'react'
import { CommonError } from 'src/domains/interfaces/CommonError'
import rawFetcher from 'src/utils/rawFetcher'
import { AdjustOrderLineMutationVariables,AdjustOrderLineMutation, RemoveOrderLineMutation, RemoveOrderLineMutationVariables } from '@framework/schema'
import { errorMapping } from 'src/utils/errrorMapping'
import rawFetcher from 'src/utils/rawFetcher'
import { useGetActiveOrder } from '.'
import { adjustOrderLineMutation } from '@framework/utils/mutations/adjust-order-line-mutation'
import { removeOrderLineMutation } from '@framework/utils/mutations/remove-order-line-mutation'
const useRemoveProductInCart = () => {
const [loading, setLoading] = useState(false)

View File

@@ -0,0 +1,13 @@
import { ActiveOrderQuery } from '@framework/schema'
import { normalizeCartForCheckout } from '@framework/utils/normalize'
import { getActiveOrderForCheckoutQuery } from '@framework/utils/queries/active-order-for-checkout-query'
import gglFetcher from 'src/utils/gglFetcher'
import useSWR from 'swr'
const useGetActiveOrderForCheckout = () => {
const { data, ...rest } = useSWR<ActiveOrderQuery>([getActiveOrderForCheckoutQuery], gglFetcher)
return { order: data?.activeOrder ? normalizeCartForCheckout(data!.activeOrder) : null, ...rest }
}
export default useGetActiveOrderForCheckout

View File

@@ -1,15 +1,15 @@
import { Cart } from '@commerce/types/cart'
import { CartCheckout } from '@commerce/types/cart'
import Link from 'next/link'
import React from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import { LANGUAGE } from 'src/utils/language.utils'
import { ButtonCommon, CardItemCheckout, EmptyCommon } from '../../../common'
import s from './CheckoutBill.module.scss'
import FormPromotionCode from './FormPromotionCode/FormPromotionCode'
import Link from 'next/link'
interface CheckoutBillProps {
// data: CardItemCheckoutProps[]
data: Cart | null
data: CartCheckout | null
}
const CheckoutBill = ({ data }: CheckoutBillProps) => {

View File

@@ -2,27 +2,30 @@ import React, { useEffect, useState } from 'react'
import { Logo } from 'src/components/common'
import CheckoutCollapse from 'src/components/common/CheckoutCollapse/CheckoutCollapse'
import { useActiveCustomer } from 'src/components/hooks/auth'
import { useGetActiveOrder } from 'src/components/hooks/cart'
import useGetActiveOrderForCheckout from 'src/components/hooks/order/useGetActiveOrderForCheckout'
import s from './CheckoutInfo.module.scss'
import CustomerInfoForm from './components/CustomerInfoForm/CustomerInfoForm'
import PaymentInfoForm from './components/PaymentInfoForm/PaymentInfoForm'
import ShippingInfoForm from './components/ShippingInfoForm/ShippingInfoForm'
import ShippingMethod from './components/ShippingMethod/ShippingMethod'
interface CheckoutInfoProps {
onViewCart: () => void
currency?: string
}
enum CheckoutStep {
export enum CheckoutStep {
CustomerInfo = 1,
ShippingInfo = 2,
PaymentInfo = 3,
ShippingAddressInfo = 2,
ShippingMethodInfo = 3,
PaymentInfo = 4,
}
const CheckoutInfo = ({ onViewCart, currency = "" }: CheckoutInfoProps) => {
const [activeStep, setActiveStep] = useState(1)
const [doneSteps, setDoneSteps] = useState<CheckoutStep[]>([])
const { order } = useGetActiveOrder()
const { order } = useGetActiveOrderForCheckout()
const { customer } = useActiveCustomer()
console.log("active order checkout: ", order)
useEffect(() => {
if (customer) {
@@ -82,7 +85,7 @@ const CheckoutInfo = ({ onViewCart, currency = "" }: CheckoutInfoProps) => {
} else {
return ''
}
case CheckoutStep.ShippingInfo:
case CheckoutStep.ShippingAddressInfo:
if (order?.shippingAddress) {
const { streetLine1, city, province, postalCode, countryCode, phoneNumber } = order.shippingAddress
return `${streetLine1}, ${city}, ${province}, ${postalCode}, ${countryCode}, ${phoneNumber}`
@@ -100,9 +103,14 @@ const CheckoutInfo = ({ onViewCart, currency = "" }: CheckoutInfoProps) => {
form: <CustomerInfoForm onConfirm={onConfirm} id={CheckoutStep.CustomerInfo} activeStep={activeStep} />,
},
{
id: CheckoutStep.ShippingInfo,
title: 'Shipping Information',
form: <ShippingInfoForm onConfirm={onConfirm} id={CheckoutStep.ShippingInfo} activeStep={activeStep} currency={currency} />,
id: CheckoutStep.ShippingAddressInfo,
title: 'Shipping Address Information',
form: <ShippingInfoForm onConfirm={onConfirm} id={CheckoutStep.ShippingAddressInfo} activeStep={activeStep}/>,
},
{
id: CheckoutStep.ShippingMethodInfo,
title: 'Shipping Method Information',
form: <ShippingMethod onConfirm={onConfirm} currency={currency} />,
},
{
id: CheckoutStep.PaymentInfo,

View File

@@ -7,15 +7,12 @@ import { LANGUAGE } from 'src/utils/language.utils'
import { CustomInputCommon } from 'src/utils/type.utils'
import * as Yup from 'yup'
import ChekoutNotePolicy from '../ChekoutNotePolicy/ChekoutNotePolicy'
import ShippingMethod from '../ShippingMethod/ShippingMethod'
import s from './ShippingInfoForm.module.scss'
interface ShippingInfoFormProps {
id: number
activeStep: number
onConfirm: (id: number) => void
currency: string
}
@@ -49,7 +46,7 @@ const provinceOptions = [
},
]
const ShippingInfoForm = ({ onConfirm, id, activeStep , currency}: ShippingInfoFormProps) => {
const ShippingInfoForm = ({ onConfirm, id, activeStep }: ShippingInfoFormProps) => {
const addressRef = useRef<CustomInputCommon>(null)
const { setOrderShippingAddress, loading } = useSetOrderShippingAddress()
const { showMessageError } = useMessage()
@@ -176,7 +173,6 @@ const ShippingInfoForm = ({ onConfirm, id, activeStep , currency}: ShippingInfoF
onEnter={isValid ? submitForm : undefined}
/>
</div>
<ShippingMethod currency={currency}/>
<div className={s.bottom}>
<ChekoutNotePolicy />
<ButtonCommon HTMLType='submit' loading={loading} size="large">

View File

@@ -4,6 +4,7 @@ import React, { memo, useState } from 'react'
import { useMessage } from 'src/components/contexts'
import { useSetOrderShippingMethod } from 'src/components/hooks/order'
import { Shipping } from 'src/components/icons'
import { CheckoutStep } from '../../CheckoutInfo'
import s from './ShippingMethod.module.scss'
import ShippingMethodItem from './ShippingMethodItem/ShippingMethodItem'
@@ -27,13 +28,15 @@ const MOCKUP_DATA = [
]
interface Props {
currency: string
onConfirm: (id: number) => void
}
const ShippingMethod = memo(({ currency }: Props) => {
const ShippingMethod = memo(({ currency, onConfirm }: Props) => {
const { setOrderShippingMethod } = useSetOrderShippingMethod()
const [selectedValue, setSelectedValue] = useState<ShippingMethodQuote>(MOCKUP_DATA[0])
const { showMessageError } = useMessage()
const [isShowOptions, setIsShowOptions] = useState<boolean>(false)
const [isShowOptions, setIsShowOptions] = useState<boolean>(true)
const onChange = (id: string) => {
const newValue = MOCKUP_DATA.find(item => item.id === id)
@@ -47,7 +50,9 @@ const ShippingMethod = memo(({ currency }: Props) => {
}
const onSubmitCalBack = (isSuccess: boolean, msg?: string) => {
if (!isSuccess) {
if (isSuccess) {
onConfirm(CheckoutStep.ShippingMethodInfo)
} else {
showMessageError(msg)
}
}

View File

@@ -2,7 +2,7 @@ import classNames from 'classnames'
import React, { useState } from 'react'
import { MessageCommon } from 'src/components/common'
import { useMessage } from 'src/components/contexts'
import { useGetActiveOrder } from 'src/components/hooks/cart'
import useGetActiveOrderForCheckout from 'src/components/hooks/order/useGetActiveOrderForCheckout'
import IconHide from 'src/components/icons/IconHide'
import { CHECKOUT_BILL_DATA } from 'src/utils/demo-data'
import { CheckoutBill, CheckoutInfo } from '..'
@@ -13,7 +13,7 @@ interface CheckoutPageProps {
const CheckoutPage = ({ }: CheckoutPageProps) => {
const { messages, removeMessage } = useMessage()
const [isShow, setIsShow] = useState(false)
const { order } = useGetActiveOrder()
const { order } = useGetActiveOrderForCheckout()
const onClose = () => {
setIsShow(false)