feat: Add update and remove item

This commit is contained in:
Alessandro Casazza 2021-08-17 18:18:39 +02:00
parent 1f0c79e68a
commit b3911fe0d1
No known key found for this signature in database
GPG Key ID: 3AF41B06C6495D3D
9 changed files with 195 additions and 24 deletions

View File

@ -1,4 +1,4 @@
import type { Product } from '@commerce/types/product'
import type { Product, ProductVariant } from '@commerce/types/product'
export type SelectedOptions = Record<string, string | null>
import { Dispatch, SetStateAction } from 'react'
@ -30,3 +30,22 @@ export function selectDefaultOptionFromProduct(
}))
})
}
export function getSelectedOptionsIds(
variant: ProductVariant,
opts: SelectedOptions
) {
const [selected] = variant.options.filter((option) => {
const type = option.displayName.toLowerCase()
const typeSelected = option.values.filter(
({ label }) => label.toLowerCase() === opts[type]
)
if (typeSelected.length > 0) return true
return false
})
return selected
? {
[`${selected.displayName?.toLowerCase()}Id`]: selected.id,
}
: {}
}

View File

@ -1,5 +1,7 @@
import Cookies, { CookieAttributes } from 'js-cookie'
export const getCookie = (name: string): string | undefined => Cookies.get(name)
const setCookie = (
name: string,
token?: string,

View File

@ -0,0 +1,7 @@
import { getCookie } from './cookies'
export default function getCredentials() {
const endpoint = process.env.NEXT_PUBLIC_COMMERCELAYER_ENDPOINT as string
const accessToken = getCookie('CL_TOKEN') as string
return { accessToken, endpoint }
}

View File

@ -0,0 +1,26 @@
export default function normalizeLineItems(lineItems: any[]) {
return lineItems.map((lineItem) => {
const id = lineItem.id
const attributes = lineItem.attributes
return {
id,
name: attributes.name,
productId: attributes.reference,
variantId: attributes.reference,
quantity: attributes.quantity,
price: attributes.unit_amount_float,
variant: {
id,
name: attributes.name,
sku: attributes.sku_code,
price: attributes.unit_amount_float,
image: {
url: `/commercelayer_assets/${attributes.reference}_FLAT.png`,
altText: 'Black Women Long Sleeve Shirt',
width: 1000,
height: 1000,
},
},
}
})
}

View File

@ -1,17 +1,67 @@
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
import { MutationHook } from '@commerce/utils/types'
import { LineItem, Order } from '@commercelayer/js-sdk'
import setCookie, { getCookie } from '@framework/api/utils/cookies'
import getCredentials from '@framework/api/utils/getCredentials'
import useCart from '@framework/cart/use-cart'
import { useCallback } from 'react'
export default useAddItem as UseAddItem<typeof handler>
export const handler: MutationHook<any> = {
fetchOptions: {
query: '',
},
async fetcher({ input, options, fetch }) {},
async fetcher({ input, options, fetch }) {
const localOrderId = localStorage.getItem('CL_ORDER')
const credentials = getCredentials()
const orderId =
localOrderId ||
(credentials.accessToken &&
(await Order.withCredentials(credentials).create({})).id)
if (orderId && input.sizeId) {
!localOrderId && localStorage.setItem('CL_ORDER', orderId)
const lineItem = await LineItem.withCredentials(credentials).create(
{
skuCode: input.sizeId,
order: Order.build({ id: orderId }),
quantity: 1,
reference: input.variantId,
_update_quantity: 1,
},
// @ts-ignore
{ rawResponse: true }
)
const attributes = lineItem.data.attributes
return {
id: lineItem.data.id,
name: attributes.name,
productId: input.productId,
variantId: input.variantId,
quantity: attributes.quantity,
price: attributes.unit_amount_float,
variant: {
id: lineItem.data.id,
name: attributes.name,
sku: input.sizeId,
price: attributes.unit_amount_float,
image: {
url: `/commercelayer_assets/${input.variantId}_FLAT.png`,
altText: 'Black Women Long Sleeve Shirt',
width: 1000,
height: 1000,
},
},
}
}
},
useHook:
({ fetch }) =>
() => {
return async function addItem() {
return {}
}
return useCallback(
async function addItem(input) {
return await fetch({ input })
},
[fetch]
)
},
}

View File

@ -1,6 +1,9 @@
import { useMemo } from 'react'
import { SWRHook } from '@commerce/utils/types'
import useCart, { UseCart } from '@commerce/cart/use-cart'
import { Order } from '@commercelayer/js-sdk'
import getCredentials from '@framework/api/utils/getCredentials'
import normalizeLineItems from '../api/utils/normalizeLineItems'
export default useCart as UseCart<typeof handler>
@ -9,6 +12,27 @@ export const handler: SWRHook<any> = {
query: '',
},
async fetcher() {
const id = localStorage.getItem('CL_ORDER') || ''
const credentials = getCredentials()
if (id && credentials.accessToken) {
const clOrder = await Order.withCredentials(credentials)
.includes('lineItems')
.find(id, { rawResponse: true })
const attributes = clOrder.data.attributes
const lineItems = clOrder?.included
? normalizeLineItems(clOrder?.included)
: []
return {
id,
createdAt: attributes.created_at,
currency: { code: attributes.currency_code },
taxesIncluded: '',
lineItems,
lineItemsSubtotalPrice: '',
subtotalPrice: attributes.subtotal_amount_float,
totalPrice: attributes.total_amount_float,
}
}
return {
id: '',
createdAt: '',
@ -22,21 +46,19 @@ export const handler: SWRHook<any> = {
},
useHook:
({ useData }) =>
(input) => {
() => {
const response = useData()
return useMemo(
() =>
Object.create(
{},
{
isEmpty: {
get() {
return true
},
enumerable: true,
Object.create(response, {
isEmpty: {
get() {
return response.data.lineItems.length === 0
},
}
),
[]
enumerable: true,
},
}),
[response]
)
},
}

View File

@ -1,5 +1,7 @@
import { MutationHook } from '@commerce/utils/types'
import useRemoveItem, { UseRemoveItem } from '@commerce/cart/use-remove-item'
import getCredentials from '@framework/api/utils/getCredentials'
import { LineItem } from '@commercelayer/js-sdk'
export default useRemoveItem as UseRemoveItem<typeof handler>
@ -7,12 +9,19 @@ export const handler: MutationHook<any> = {
fetchOptions: {
query: '',
},
async fetcher({ input, options, fetch }) {},
async fetcher({ input: { id } }) {
const credentials = getCredentials()
const orderId = localStorage.getItem('CL_ORDER')
if (orderId && id) {
await LineItem.build({ id }).withCredentials(credentials).destroy()
return {}
}
},
useHook:
({ fetch }) =>
() => {
return async function removeItem(input) {
return {}
return await fetch({ input })
}
},
}

View File

@ -1,5 +1,9 @@
import { MutationHook } from '@commerce/utils/types'
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
import useCart from '@commerce/cart/use-cart'
import { useCallback } from 'react'
import getCredentials from '@framework/api/utils/getCredentials'
import { LineItem } from '@commercelayer/js-sdk'
export default useUpdateItem as UseUpdateItem<any>
@ -7,12 +11,44 @@ export const handler: MutationHook<any> = {
fetchOptions: {
query: '',
},
async fetcher({ input, options, fetch }) {},
async fetcher({ input: { item, quantity } }) {
const credentials = getCredentials()
const orderId = localStorage.getItem('CL_ORDER')
if (orderId && item.id) {
const lineItem = (await LineItem.build({
id: item.id,
})
.withCredentials(credentials)
// @ts-ignore
.update({ quantity }, null, { rawResponse: true })) as any
const attributes = lineItem.data.attributes
return {
id: lineItem.data.id,
name: attributes.name,
productId: item.productId,
variantId: item.variantId,
quantity: attributes.quantity,
price: attributes.unit_amount_float,
variant: {
id: lineItem.data.id,
name: attributes.name,
sku: lineItem.data.sku_code,
price: attributes.unit_amount_float,
image: {
url: `/commercelayer_assets/${item.variantId}_FLAT.png`,
altText: 'Black Women Long Sleeve Shirt',
width: 1000,
height: 1000,
},
},
}
}
},
useHook:
({ fetch }) =>
() => {
return async function addItem() {
return {}
({ item }) => {
return async function updateItem(input) {
return await fetch({ input: { item, ...input } })
}
},
}

View File

@ -2,7 +2,7 @@
"provider": "commercelayer",
"features": {
"wishlist": false,
"cart": false,
"cart": true,
"search": false,
"customerAuth": true
}