mirror of
https://github.com/vercel/commerce.git
synced 2025-03-14 22:42:33 +00:00
Updated types, hooks, useCustomer sample
This commit is contained in:
parent
40049b27a1
commit
444456d376
@ -10,14 +10,16 @@ const getCart: CartHandlers['getCart'] = async ({
|
||||
}) => {
|
||||
let result: { data?: Cart } = {}
|
||||
|
||||
try {
|
||||
result = await config.storeApiFetch(`/v3/carts/${cartId}`)
|
||||
} catch (error) {
|
||||
if (error instanceof BigcommerceApiError && error.status === 404) {
|
||||
// Remove the cookie if it exists but the cart wasn't found
|
||||
res.setHeader('Set-Cookie', getCartCookie(config.cartCookie))
|
||||
} else {
|
||||
throw error
|
||||
if (cartId) {
|
||||
try {
|
||||
result = await config.storeApiFetch(`/v3/carts/${cartId}`)
|
||||
} catch (error) {
|
||||
if (error instanceof BigcommerceApiError && error.status === 404) {
|
||||
// Remove the cookie if it exists but the cart wasn't found
|
||||
res.setHeader('Set-Cookie', getCartCookie(config.cartCookie))
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GetLoggedInCustomerQuery } from '@lib/bigcommerce/schema'
|
||||
import type { GetLoggedInCustomerQuery } from '@lib/bigcommerce/schema'
|
||||
import type { CustomersHandlers } from '..'
|
||||
|
||||
export const getLoggedInCustomerQuery = /* GraphQL */ `
|
||||
@ -22,23 +22,40 @@ export const getLoggedInCustomerQuery = /* GraphQL */ `
|
||||
}
|
||||
`
|
||||
|
||||
export type Customer = NonNullable<GetLoggedInCustomerQuery['customer']>
|
||||
|
||||
const getLoggedInCustomer: CustomersHandlers['getLoggedInCustomer'] = async ({
|
||||
req,
|
||||
res,
|
||||
config,
|
||||
}) => {
|
||||
const { data } = await config.fetch<GetLoggedInCustomerQuery>(
|
||||
getLoggedInCustomerQuery
|
||||
)
|
||||
const { customer } = data
|
||||
const token = req.cookies[config.customerCookie]
|
||||
|
||||
if (!customer) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Customer not found', code: 'not_found' }],
|
||||
})
|
||||
if (token) {
|
||||
const { data } = await config.fetch<GetLoggedInCustomerQuery>(
|
||||
getLoggedInCustomerQuery,
|
||||
undefined,
|
||||
{
|
||||
headers: {
|
||||
cookie: `${config.customerCookie}=${token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
const { customer } = data
|
||||
|
||||
console.log('CUSTOMER', customer)
|
||||
|
||||
if (!customer) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Customer not found', code: 'not_found' }],
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(200).json({ data: { customer } })
|
||||
}
|
||||
|
||||
res.status(200).json({ data: { customer } })
|
||||
res.status(200).json({ data: null })
|
||||
}
|
||||
|
||||
export default getLoggedInCustomer
|
||||
|
@ -4,16 +4,18 @@ import createApiHandler, {
|
||||
} from '../utils/create-api-handler'
|
||||
import isAllowedMethod from '../utils/is-allowed-method'
|
||||
import { BigcommerceApiError } from '../utils/errors'
|
||||
import getLoggedInCustomer from './handlers/get-logged-in-customer'
|
||||
import getLoggedInCustomer, {
|
||||
Customer,
|
||||
} from './handlers/get-logged-in-customer'
|
||||
|
||||
export type Customer = any
|
||||
export type { Customer }
|
||||
|
||||
export type CustomerData = {
|
||||
customer: Customer
|
||||
}
|
||||
|
||||
export type CustomersHandlers = {
|
||||
getLoggedInCustomer: BigcommerceHandler<CustomerData, null>
|
||||
getLoggedInCustomer: BigcommerceHandler<CustomerData>
|
||||
}
|
||||
|
||||
const METHODS = ['GET']
|
||||
@ -25,10 +27,8 @@ const customersApi: BigcommerceApiHandler<
|
||||
if (!isAllowedMethod(req, res, METHODS)) return
|
||||
|
||||
try {
|
||||
if (req.method === 'GET') {
|
||||
const body = null
|
||||
return await handlers['getLoggedInCustomer']({ req, res, config, body })
|
||||
}
|
||||
const body = null
|
||||
return await handlers['getLoggedInCustomer']({ req, res, config, body })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
|
@ -1,36 +1,33 @@
|
||||
import { ConfigInterface } from 'swr'
|
||||
import { HookFetcher } from '@lib/commerce/utils/types'
|
||||
import useCommerceCustomer, { CustomerInput } from '@lib/commerce/use-customer'
|
||||
import type { SwrOptions } from '@lib/commerce/utils/use-data'
|
||||
import useCommerceCustomer from '@lib/commerce/use-customer'
|
||||
import type { Customer, CustomerData } from './api/customers'
|
||||
|
||||
const defaultOpts = {
|
||||
url: '/api/bigcommerce/customer',
|
||||
url: '/api/bigcommerce/customers',
|
||||
method: 'GET',
|
||||
}
|
||||
|
||||
export type { Customer }
|
||||
|
||||
export const fetcher: HookFetcher<CustomerData | null, CustomerInput> = (
|
||||
export const fetcher: HookFetcher<Customer | null> = async (
|
||||
options,
|
||||
{ cartId },
|
||||
_,
|
||||
fetch
|
||||
) => {
|
||||
return cartId ? fetch({ ...defaultOpts, ...options }) : null
|
||||
const data = await fetch<CustomerData>({ ...defaultOpts, ...options })
|
||||
return data.customer
|
||||
}
|
||||
|
||||
export function extendHook(
|
||||
customFetcher: typeof fetcher,
|
||||
swrOptions?: ConfigInterface
|
||||
swrOptions?: SwrOptions<Customer | null>
|
||||
) {
|
||||
const useCustomer = () => {
|
||||
const cart = useCommerceCustomer<CustomerData | null>(
|
||||
defaultOpts,
|
||||
[],
|
||||
customFetcher,
|
||||
{ revalidateOnFocus: false, ...swrOptions }
|
||||
)
|
||||
|
||||
return cart
|
||||
return useCommerceCustomer(defaultOpts, [], customFetcher, {
|
||||
revalidateOnFocus: false,
|
||||
...swrOptions,
|
||||
})
|
||||
}
|
||||
|
||||
useCustomer.extend = extendHook
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { responseInterface, ConfigInterface } from 'swr'
|
||||
import type { responseInterface, ConfigInterface } from 'swr'
|
||||
import Cookies from 'js-cookie'
|
||||
import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
|
||||
import useData from '../utils/use-data'
|
||||
|
@ -1,30 +1,5 @@
|
||||
import { responseInterface, ConfigInterface } from 'swr'
|
||||
import Cookies from 'js-cookie'
|
||||
import type { HookInput, HookFetcher, HookFetcherOptions } from './utils/types'
|
||||
import useData from './utils/use-data'
|
||||
import { useCommerce } from '.'
|
||||
|
||||
export type CustomerResponse<T> = responseInterface<T, Error>
|
||||
const useCustomer = useData
|
||||
|
||||
export type CustomerInput = {
|
||||
cartId: string | undefined
|
||||
}
|
||||
|
||||
export default function useCustomer<T>(
|
||||
options: HookFetcherOptions,
|
||||
input: HookInput,
|
||||
fetcherFn: HookFetcher<T | null, CustomerInput>,
|
||||
swrOptions?: ConfigInterface<T | null>
|
||||
) {
|
||||
// TODO: Replace this with the login cookie
|
||||
const { cartCookie } = useCommerce()
|
||||
|
||||
const fetcher: typeof fetcherFn = (options, input, fetch) => {
|
||||
input.cartId = Cookies.get(cartCookie)
|
||||
return fetcherFn(options, input, fetch)
|
||||
}
|
||||
|
||||
const response = useData(options, input, fetcher, swrOptions)
|
||||
|
||||
return response as CustomerResponse<T>
|
||||
}
|
||||
export default useCustomer
|
||||
|
@ -9,11 +9,11 @@ export type FetcherOptions = {
|
||||
body?: any
|
||||
}
|
||||
|
||||
export type HookFetcher<T, Input = null> = (
|
||||
export type HookFetcher<Result, Input = null> = (
|
||||
options: HookFetcherOptions | null,
|
||||
input: Input,
|
||||
fetch: Fetcher<T>
|
||||
) => T | Promise<T>
|
||||
fetch: <T = Result>(options: FetcherOptions) => Promise<T>
|
||||
) => Result | Promise<Result>
|
||||
|
||||
export type HookFetcherOptions = {
|
||||
query?: string
|
||||
|
@ -1,13 +1,22 @@
|
||||
import useSWR, { ConfigInterface } from 'swr'
|
||||
import useSWR, { ConfigInterface, responseInterface } from 'swr'
|
||||
import type { HookInput, HookFetcher, HookFetcherOptions } from './types'
|
||||
import { CommerceError } from './errors'
|
||||
import { useCommerce } from '..'
|
||||
|
||||
export default function useData<T, Input = any>(
|
||||
export type SwrOptions<Result, Input = null> = ConfigInterface<
|
||||
Result,
|
||||
CommerceError,
|
||||
HookFetcher<Result, Input>
|
||||
>
|
||||
|
||||
export type UseData = <Result = any, Input = null>(
|
||||
options: HookFetcherOptions | (() => HookFetcherOptions | null),
|
||||
input: HookInput,
|
||||
fetcherFn: HookFetcher<T, Input>,
|
||||
swrOptions?: ConfigInterface<T>
|
||||
) {
|
||||
fetcherFn: HookFetcher<Result, Input>,
|
||||
swrOptions?: SwrOptions<Result, Input>
|
||||
) => responseInterface<Result, CommerceError>
|
||||
|
||||
const useData: UseData = (options, input, fetcherFn, swrOptions) => {
|
||||
const { fetcherRef } = useCommerce()
|
||||
const fetcher = (
|
||||
url?: string,
|
||||
@ -25,7 +34,6 @@ export default function useData<T, Input = any>(
|
||||
fetcherRef.current
|
||||
)
|
||||
}
|
||||
|
||||
const response = useSWR(
|
||||
() => {
|
||||
const opts = typeof options === 'function' ? options() : options
|
||||
@ -39,3 +47,5 @@ export default function useData<T, Input = any>(
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
export default useData
|
||||
|
@ -3,11 +3,15 @@ import { Layout } from '@components/core'
|
||||
import { Logo, Modal, Button } from '@components/ui'
|
||||
import useLogin from '@lib/bigcommerce/use-login'
|
||||
import useLogout from '@lib/bigcommerce/use-logout'
|
||||
import useCustomer from '@lib/bigcommerce/use-customer'
|
||||
|
||||
export default function Login() {
|
||||
const signup = useSignup()
|
||||
const login = useLogin()
|
||||
const logout = useLogout()
|
||||
// Data about the currently logged in customer, it will update
|
||||
// automatically after a signup/login/logout
|
||||
const { data } = useCustomer()
|
||||
// TODO: use this method. It can take more than 5 seconds to do a signup
|
||||
const handleSignup = async () => {
|
||||
// TODO: validate the password and email before calling the signup
|
||||
|
Loading…
x
Reference in New Issue
Block a user