mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 23:16:59 +00:00
feat: Update hooks
This commit is contained in:
parent
a9e2d75f14
commit
f11ff29e3b
@ -1,54 +1,52 @@
|
||||
import useAddItem, { UseAddItem } from '@vercel/commerce/cart/use-add-item'
|
||||
import { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import { LineItem, Order } from '@commercelayer/js-sdk'
|
||||
import getCredentials from '../api/utils/getCredentials'
|
||||
import CLSdk from '@commercelayer/sdk'
|
||||
import getCredentials, {
|
||||
getOrganizationSlug,
|
||||
} from '../api/utils/getCredentials'
|
||||
import useCart from '../cart/use-cart'
|
||||
import { useCallback } from 'react'
|
||||
import getContentData from '../api/utils/getContentData'
|
||||
|
||||
export default useAddItem as UseAddItem<typeof handler>
|
||||
export const handler: MutationHook<any> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
},
|
||||
async fetcher({ input, options, fetch }) {
|
||||
async fetcher({ input }) {
|
||||
const localOrderId = localStorage.getItem('CL_ORDER_ID')
|
||||
const credentials = getCredentials()
|
||||
const { accessToken, endpoint } = getCredentials()
|
||||
const organization = getOrganizationSlug(endpoint).organization
|
||||
const sdk = CLSdk({
|
||||
accessToken,
|
||||
organization,
|
||||
})
|
||||
const orderId =
|
||||
localOrderId ||
|
||||
(credentials.accessToken &&
|
||||
(await Order.withCredentials(credentials).create({})).id)
|
||||
localOrderId || (accessToken && (await sdk.orders.create({})).id)
|
||||
if (orderId && input.variantId) {
|
||||
!localOrderId && localStorage.setItem('CL_ORDER_ID', orderId)
|
||||
const lineItem = await LineItem.withCredentials(credentials).create(
|
||||
{
|
||||
skuCode: input.variantId,
|
||||
order: Order.build({ id: orderId }),
|
||||
const [product] = await getContentData(input.productId)
|
||||
const [image] = product.images
|
||||
const lineItem = await sdk.line_items.create({
|
||||
sku_code: input.variantId,
|
||||
order: sdk.orders.relationship(orderId),
|
||||
quantity: 1,
|
||||
reference: input.productId,
|
||||
_update_quantity: 1,
|
||||
},
|
||||
// @ts-ignore
|
||||
{ rawResponse: true }
|
||||
)
|
||||
const attributes = lineItem.data.attributes
|
||||
_update_quantity: true,
|
||||
})
|
||||
return {
|
||||
id: lineItem.data.id,
|
||||
name: attributes.name,
|
||||
id: lineItem.id,
|
||||
name: lineItem.name,
|
||||
productId: input.productId,
|
||||
variantId: input.variantId,
|
||||
quantity: attributes.quantity,
|
||||
price: attributes.unit_amount_float,
|
||||
quantity: lineItem.quantity,
|
||||
price: lineItem.unit_amount_float,
|
||||
variant: {
|
||||
id: lineItem.data.id,
|
||||
name: attributes.name,
|
||||
id: lineItem.id,
|
||||
name: lineItem.name,
|
||||
sku: input.variantId,
|
||||
price: attributes.unit_amount_float,
|
||||
image: {
|
||||
url: `https://data.commercelayer.app/vercel-provider/${input.productId}_FLAT.png`,
|
||||
altText: attributes.name,
|
||||
width: 1000,
|
||||
height: 1000,
|
||||
},
|
||||
price: lineItem.unit_amount_float,
|
||||
image,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -57,6 +55,7 @@ export const handler: MutationHook<any> = {
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { mutate } = useCart()
|
||||
|
||||
return useCallback(
|
||||
async function addItem(input) {
|
||||
const data = await fetch({ input })
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { useMemo } from 'react'
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useCart, { UseCart } from '@vercel/commerce/cart/use-cart'
|
||||
import { Order } from '@commercelayer/js-sdk'
|
||||
import getCredentials from '../api/utils/getCredentials'
|
||||
import CLSdk from '@commercelayer/sdk'
|
||||
import getCredentials, {
|
||||
getOrganizationSlug,
|
||||
} from '../api/utils/getCredentials'
|
||||
import normalizeLineItems from '../api/utils/normalizeLineItems'
|
||||
|
||||
export default useCart as UseCart<typeof handler>
|
||||
@ -14,25 +16,27 @@ export const handler: SWRHook<any> = {
|
||||
async fetcher() {
|
||||
const id = localStorage.getItem('CL_ORDER_ID') || ''
|
||||
const credentials = getCredentials()
|
||||
const organization = getOrganizationSlug(credentials.endpoint).organization
|
||||
const sdk = CLSdk({
|
||||
accessToken: credentials.accessToken,
|
||||
organization,
|
||||
})
|
||||
if (id && credentials.accessToken) {
|
||||
const clOrder = await Order.withCredentials(credentials)
|
||||
.includes('lineItems')
|
||||
.find(id, { rawResponse: true })
|
||||
const attributes = clOrder.data.attributes
|
||||
const orderStatus = attributes.status
|
||||
if (['pending', 'draft'].includes(orderStatus)) {
|
||||
const lineItems = clOrder?.included
|
||||
? normalizeLineItems(clOrder?.included)
|
||||
const order = await sdk.orders.retrieve(id, { include: ['line_items'] })
|
||||
const orderStatus = order.status
|
||||
if (orderStatus && ['pending', 'draft'].includes(orderStatus)) {
|
||||
const lineItems = order.line_items
|
||||
? normalizeLineItems(order.line_items)
|
||||
: []
|
||||
return {
|
||||
id,
|
||||
createdAt: attributes.created_at,
|
||||
currency: { code: attributes.currency_code },
|
||||
createdAt: order.created_at,
|
||||
currency: { code: order.currency_code },
|
||||
taxesIncluded: '',
|
||||
lineItems,
|
||||
lineItemsSubtotalPrice: '',
|
||||
subtotalPrice: attributes.subtotal_amount_float,
|
||||
totalPrice: attributes.total_amount_float,
|
||||
subtotalPrice: order.subtotal_amount_float,
|
||||
totalPrice: order.total_amount_float,
|
||||
}
|
||||
} else if (id) {
|
||||
localStorage.removeItem('CL_ORDER_ID')
|
||||
@ -53,6 +57,7 @@ export const handler: SWRHook<any> = {
|
||||
({ useData }) =>
|
||||
() => {
|
||||
const response = useData()
|
||||
console.log('response', response)
|
||||
return useMemo(
|
||||
() =>
|
||||
Object.create(response, {
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import useRemoveItem, { UseRemoveItem } from '@vercel/commerce/cart/use-remove-item'
|
||||
import getCredentials from '../api/utils/getCredentials'
|
||||
import { LineItem } from '@commercelayer/js-sdk'
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
} from '@vercel/commerce/cart/use-remove-item'
|
||||
import getCredentials, {
|
||||
getOrganizationSlug,
|
||||
} from '../api/utils/getCredentials'
|
||||
import CLSdk from '@commercelayer/sdk'
|
||||
import useCart from './use-cart'
|
||||
|
||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||
@ -13,8 +17,13 @@ export const handler: MutationHook<any> = {
|
||||
async fetcher({ input: { id } }) {
|
||||
const credentials = getCredentials()
|
||||
const orderId = localStorage.getItem('CL_ORDER_ID')
|
||||
const organization = getOrganizationSlug(credentials.endpoint).organization
|
||||
const sdk = CLSdk({
|
||||
accessToken: credentials.accessToken,
|
||||
organization,
|
||||
})
|
||||
if (orderId && id) {
|
||||
await LineItem.build({ id }).withCredentials(credentials).destroy()
|
||||
await sdk.line_items.delete(id)
|
||||
return {}
|
||||
}
|
||||
},
|
||||
|
@ -1,8 +1,13 @@
|
||||
import { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import useUpdateItem, { UseUpdateItem } from '@vercel/commerce/cart/use-update-item'
|
||||
import useUpdateItem, {
|
||||
UseUpdateItem,
|
||||
} from '@vercel/commerce/cart/use-update-item'
|
||||
import useCart from '../cart/use-cart'
|
||||
import getCredentials from '../api/utils/getCredentials'
|
||||
import { LineItem } from '@commercelayer/js-sdk'
|
||||
import getCredentials, {
|
||||
getOrganizationSlug,
|
||||
} from '../api/utils/getCredentials'
|
||||
import CLSdk from '@commercelayer/sdk'
|
||||
import getContentData from '../api/utils/getContentData'
|
||||
|
||||
export default useUpdateItem as UseUpdateItem<any>
|
||||
|
||||
@ -12,33 +17,29 @@ export const handler: MutationHook<any> = {
|
||||
},
|
||||
async fetcher({ input: { item, quantity } }) {
|
||||
const credentials = getCredentials()
|
||||
const organization = getOrganizationSlug(credentials.endpoint).organization
|
||||
const sdk = CLSdk({
|
||||
accessToken: credentials.accessToken,
|
||||
organization,
|
||||
})
|
||||
const orderId = localStorage.getItem('CL_ORDER_ID')
|
||||
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
|
||||
const lineItem = await sdk.line_items.update({ id: item.id, quantity })
|
||||
const [product] = await getContentData(item.productId)
|
||||
const [image] = product.images
|
||||
return {
|
||||
id: lineItem.data.id,
|
||||
name: attributes.name,
|
||||
id: lineItem.id,
|
||||
name: lineItem.name,
|
||||
productId: item.productId,
|
||||
variantId: item.variantId,
|
||||
quantity: attributes.quantity,
|
||||
price: attributes.unit_amount_float,
|
||||
quantity: lineItem.quantity,
|
||||
price: lineItem.unit_amount_float,
|
||||
variant: {
|
||||
id: lineItem.data.id,
|
||||
name: attributes.name,
|
||||
sku: lineItem.data.sku_code,
|
||||
price: attributes.unit_amount_float,
|
||||
image: {
|
||||
url: `https://data.commercelayer.app/vercel-provider/${item.variantId}_FLAT.png`,
|
||||
altText: 'Black Women Long Sleeve Shirt',
|
||||
width: 1000,
|
||||
height: 1000,
|
||||
},
|
||||
id: lineItem.id,
|
||||
name: lineItem.name,
|
||||
sku: lineItem.sku_code,
|
||||
price: lineItem.unit_amount_float,
|
||||
image,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import * as React from 'react'
|
||||
import { ReactNode } from 'react'
|
||||
import { CommercelayerProvider } from './provider'
|
||||
import {
|
||||
|
@ -1,19 +1,20 @@
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useSearch, { UseSearch } from '@vercel/commerce/product/use-search'
|
||||
import data from '../data.json'
|
||||
import getContentData from '../api/utils/getContentData'
|
||||
import type { Products } from '../api/utils/getContentData'
|
||||
export default useSearch as UseSearch<typeof handler>
|
||||
|
||||
const productsFinder = (s: string, c?: string, b?: string) => {
|
||||
const { products } = data
|
||||
const productsFinder = (
|
||||
products: Products,
|
||||
s: string,
|
||||
c?: string,
|
||||
b?: string
|
||||
) => {
|
||||
let p = products
|
||||
if (s)
|
||||
p = p.filter((p) => p.name.toLowerCase().search(s.toLowerCase()) !== -1)
|
||||
if (s) p = p.filter((p) => p.name.toLowerCase().includes(s.toLowerCase()))
|
||||
if (c)
|
||||
p = p.filter(
|
||||
(p) => p.categoryId.toLowerCase().search(c.toLowerCase()) !== -1
|
||||
)
|
||||
if (b)
|
||||
p = p.filter((p) => p.brandId.toLowerCase().search(b.toLowerCase()) !== -1)
|
||||
p = p.filter((p) => p.categoryId.toLowerCase().includes(c.toLowerCase()))
|
||||
if (b) p = p.filter((p) => p.brandId.toLowerCase().includes(b.toLowerCase()))
|
||||
return p
|
||||
}
|
||||
|
||||
@ -21,19 +22,33 @@ export const handler: SWRHook<any> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
},
|
||||
async fetcher({ input, options, fetch }) {},
|
||||
useHook:
|
||||
({ useData }) =>
|
||||
({ search, categoryId, brandId }) => {
|
||||
const products = productsFinder(search, categoryId, brandId)
|
||||
return {
|
||||
data:
|
||||
products.length > 0
|
||||
async fetcher({ input }) {
|
||||
const { search, categoryId, brandId } = input
|
||||
const contentData = await getContentData()
|
||||
const products = productsFinder(contentData, search, categoryId, brandId)
|
||||
return products.length > 0
|
||||
? {
|
||||
products,
|
||||
found: true,
|
||||
}
|
||||
: data,
|
||||
: {
|
||||
products: contentData,
|
||||
}
|
||||
},
|
||||
useHook:
|
||||
({ useData }) =>
|
||||
(input = {}) => {
|
||||
return useData({
|
||||
input: [
|
||||
['search', input.search],
|
||||
['categoryId', input.categoryId],
|
||||
['brandId', input.brandId],
|
||||
['sort', input.sort],
|
||||
],
|
||||
swrOptions: {
|
||||
revalidateOnFocus: false,
|
||||
...input.swrOptions,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import { handler as useSearch } from './product/use-search'
|
||||
import { handler as useLogin } from './auth/use-login'
|
||||
import { handler as useLogout } from './auth/use-logout'
|
||||
import { handler as useSignup } from './auth/use-signup'
|
||||
import { handler as useWishlist } from './wishlist/use-wishlist'
|
||||
import { handler as useWishlistAddItem } from './wishlist/use-add-item'
|
||||
import { handler as useWishlistRemoveItem } from './wishlist/use-remove-item'
|
||||
|
||||
export const CommercelayerProvider = {
|
||||
locale: 'en-US',
|
||||
@ -18,6 +21,11 @@ export const CommercelayerProvider = {
|
||||
customer: { useCustomer },
|
||||
products: { useSearch },
|
||||
auth: { useLogin, useLogout, useSignup },
|
||||
wishlist: {
|
||||
useWishlist,
|
||||
useAddItem: useWishlistAddItem,
|
||||
useRemoveItem: useWishlistRemoveItem,
|
||||
},
|
||||
}
|
||||
|
||||
export type Provider = typeof CommercelayerProvider
|
@ -1,22 +1,48 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import useAddItem, { UseAddItem } from '@vercel/commerce/wishlist/use-add-item'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import { useCallback } from 'react'
|
||||
import { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import useWishlist from './use-wishlist'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
export default useAddItem as UseAddItem<typeof handler>
|
||||
|
||||
export function emptyHook() {
|
||||
const useEmptyHook = async (options: any = {}) => {
|
||||
export const handler: MutationHook<any> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
},
|
||||
async fetcher({ input }) {
|
||||
const { variantId } = input
|
||||
let wishlist = []
|
||||
const localWishlist = localStorage.getItem('wishlist')
|
||||
if (localWishlist) {
|
||||
wishlist = JSON.parse(localWishlist)
|
||||
if (!wishlist.includes(options.variantId)) {
|
||||
wishlist.push(options.variantId)
|
||||
if (!wishlist.includes(variantId)) {
|
||||
wishlist.push(variantId)
|
||||
}
|
||||
} else {
|
||||
wishlist.push(options.variantId)
|
||||
wishlist.push(variantId)
|
||||
}
|
||||
localStorage.setItem('wishlist', JSON.stringify(wishlist))
|
||||
return wishlist
|
||||
},
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { mutate } = useWishlist()
|
||||
const { data: customer } = useCustomer()
|
||||
return useCallback(
|
||||
async function addItem(input) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
|
||||
return useEmptyHook
|
||||
const data = await fetch({ input })
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export default emptyHook
|
||||
|
@ -1,20 +1,46 @@
|
||||
type Options = {
|
||||
includeProducts?: boolean
|
||||
}
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
} from '@vercel/commerce/wishlist/use-remove-item'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import { useCallback } from 'react'
|
||||
import { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import useWishlist from './use-wishlist'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||
|
||||
export function emptyHook(options?: Options) {
|
||||
const useEmptyHook = async ({ id }: { id: string | number }) => {
|
||||
export const handler: MutationHook<any> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
},
|
||||
async fetcher({ input }) {
|
||||
const { id } = input
|
||||
let wishlist = []
|
||||
const localWishlist = localStorage.getItem('wishlist')
|
||||
if (localWishlist) {
|
||||
wishlist = JSON.parse(localWishlist)
|
||||
wishlist = wishlist.filter((p: string) => p !== id)
|
||||
wishlist = wishlist.filter((_p: string, key: number) => key !== id)
|
||||
}
|
||||
localStorage.setItem('wishlist', JSON.stringify(wishlist))
|
||||
return wishlist
|
||||
},
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { mutate } = useWishlist()
|
||||
const { data: customer } = useCustomer()
|
||||
return useCallback(
|
||||
async function addItem(input) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
|
||||
return useEmptyHook
|
||||
const data = await fetch({ input })
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export default emptyHook
|
||||
|
@ -1,46 +1,24 @@
|
||||
import { HookFetcher } from '@vercel/commerce/utils/types'
|
||||
import type { Product } from '@vercel/commerce/types/product'
|
||||
import data from '../data.json'
|
||||
import { useCustomer } from '../customer'
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useWishlist, {
|
||||
UseWishlist,
|
||||
} from '@vercel/commerce/wishlist/use-wishlist'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import getContentData from '../api/utils/getContentData'
|
||||
export default useWishlist as UseWishlist<typeof handler>
|
||||
|
||||
const defaultOpts = {}
|
||||
|
||||
export type Wishlist = {
|
||||
items: [
|
||||
{
|
||||
variant_id: number
|
||||
product_id: number
|
||||
id: number
|
||||
product: Product
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export interface UseWishlistOptions {
|
||||
includeProducts?: boolean
|
||||
}
|
||||
|
||||
export interface UseWishlistInput extends UseWishlistOptions {
|
||||
customerId?: number
|
||||
}
|
||||
|
||||
export const fetcher: HookFetcher<Wishlist | null, UseWishlistInput> = () => {
|
||||
return null
|
||||
}
|
||||
|
||||
export function extendHook(
|
||||
customFetcher: typeof fetcher,
|
||||
// swrOptions?: SwrOptions<Wishlist | null, UseWishlistInput>
|
||||
swrOptions?: any
|
||||
) {
|
||||
const useWishlist = ({ includeProducts }: UseWishlistOptions = {}) => {
|
||||
const { data: customer } = useCustomer()
|
||||
export const handler: SWRHook<any> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
},
|
||||
async fetcher({ input }) {
|
||||
const { customerEmail } = input
|
||||
const getWishlist =
|
||||
typeof localStorage !== 'undefined' && localStorage.getItem('wishlist')
|
||||
if (getWishlist && customer?.email && data.products.length > 0) {
|
||||
const products = await getContentData()
|
||||
if (getWishlist && customerEmail && products.length > 0) {
|
||||
const wishlist = JSON.parse(getWishlist)
|
||||
const items = wishlist.map((wishlist: string, id: number) => {
|
||||
const [product] = data.products.filter((p) =>
|
||||
const [product] = products.filter((p) =>
|
||||
wishlist.startsWith(p.id)
|
||||
) as any
|
||||
const [variant] = product?.variants
|
||||
@ -51,14 +29,20 @@ export function extendHook(
|
||||
product,
|
||||
}
|
||||
})
|
||||
return { data: { items } }
|
||||
return { items }
|
||||
}
|
||||
return { data: null }
|
||||
return { items: [] }
|
||||
},
|
||||
useHook:
|
||||
({ useData }) =>
|
||||
(input = {}) => {
|
||||
const { data: customer } = useCustomer()
|
||||
return useData({
|
||||
input: [['customerEmail', customer?.email]],
|
||||
swrOptions: {
|
||||
revalidateOnFocus: true,
|
||||
...input.swrOptions,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
useWishlist.extend = extendHook
|
||||
|
||||
return useWishlist
|
||||
}
|
||||
|
||||
export default extendHook(fetcher)
|
||||
|
Loading…
x
Reference in New Issue
Block a user