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