mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 07:26:59 +00:00
feat: Add update and remove item
This commit is contained in:
parent
1f0c79e68a
commit
b3911fe0d1
@ -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>
|
export type SelectedOptions = Record<string, string | null>
|
||||||
import { Dispatch, SetStateAction } from 'react'
|
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,
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import Cookies, { CookieAttributes } from 'js-cookie'
|
import Cookies, { CookieAttributes } from 'js-cookie'
|
||||||
|
|
||||||
|
export const getCookie = (name: string): string | undefined => Cookies.get(name)
|
||||||
|
|
||||||
const setCookie = (
|
const setCookie = (
|
||||||
name: string,
|
name: string,
|
||||||
token?: string,
|
token?: string,
|
||||||
|
7
framework/commercelayer/api/utils/getCredentials.ts
Normal file
7
framework/commercelayer/api/utils/getCredentials.ts
Normal 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 }
|
||||||
|
}
|
26
framework/commercelayer/api/utils/normalizeLineItems.tsx
Normal file
26
framework/commercelayer/api/utils/normalizeLineItems.tsx
Normal 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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -1,17 +1,67 @@
|
|||||||
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
||||||
import { MutationHook } from '@commerce/utils/types'
|
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 default useAddItem as UseAddItem<typeof handler>
|
||||||
export const handler: MutationHook<any> = {
|
export const handler: MutationHook<any> = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: '',
|
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:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
return async function addItem() {
|
return useCallback(
|
||||||
return {}
|
async function addItem(input) {
|
||||||
}
|
return await fetch({ input })
|
||||||
|
},
|
||||||
|
[fetch]
|
||||||
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { SWRHook } from '@commerce/utils/types'
|
import { SWRHook } from '@commerce/utils/types'
|
||||||
import useCart, { UseCart } from '@commerce/cart/use-cart'
|
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>
|
export default useCart as UseCart<typeof handler>
|
||||||
|
|
||||||
@ -9,6 +12,27 @@ export const handler: SWRHook<any> = {
|
|||||||
query: '',
|
query: '',
|
||||||
},
|
},
|
||||||
async fetcher() {
|
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 {
|
return {
|
||||||
id: '',
|
id: '',
|
||||||
createdAt: '',
|
createdAt: '',
|
||||||
@ -22,21 +46,19 @@ export const handler: SWRHook<any> = {
|
|||||||
},
|
},
|
||||||
useHook:
|
useHook:
|
||||||
({ useData }) =>
|
({ useData }) =>
|
||||||
(input) => {
|
() => {
|
||||||
|
const response = useData()
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() =>
|
() =>
|
||||||
Object.create(
|
Object.create(response, {
|
||||||
{},
|
isEmpty: {
|
||||||
{
|
get() {
|
||||||
isEmpty: {
|
return response.data.lineItems.length === 0
|
||||||
get() {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
},
|
},
|
||||||
}
|
enumerable: true,
|
||||||
),
|
},
|
||||||
[]
|
}),
|
||||||
|
[response]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { MutationHook } from '@commerce/utils/types'
|
import { MutationHook } from '@commerce/utils/types'
|
||||||
import useRemoveItem, { UseRemoveItem } from '@commerce/cart/use-remove-item'
|
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>
|
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||||
|
|
||||||
@ -7,12 +9,19 @@ export const handler: MutationHook<any> = {
|
|||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: '',
|
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:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
return async function removeItem(input) {
|
return async function removeItem(input) {
|
||||||
return {}
|
return await fetch({ input })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { MutationHook } from '@commerce/utils/types'
|
import { MutationHook } from '@commerce/utils/types'
|
||||||
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
|
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>
|
export default useUpdateItem as UseUpdateItem<any>
|
||||||
|
|
||||||
@ -7,12 +11,44 @@ export const handler: MutationHook<any> = {
|
|||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: '',
|
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:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
({ item }) => {
|
||||||
return async function addItem() {
|
return async function updateItem(input) {
|
||||||
return {}
|
return await fetch({ input: { item, ...input } })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"provider": "commercelayer",
|
"provider": "commercelayer",
|
||||||
"features": {
|
"features": {
|
||||||
"wishlist": false,
|
"wishlist": false,
|
||||||
"cart": false,
|
"cart": true,
|
||||||
"search": false,
|
"search": false,
|
||||||
"customerAuth": true
|
"customerAuth": true
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user