Add codes for fetching of vendor data

Add swr function useVendors
Add types for Vendor
Add useVendors to spreeProvider vendors
Add noopApi for spree vendors api
Add page vendors.tsx to test rendering of fetched vendor data using useVendors
This commit is contained in:
Godfrey Peralta 2022-08-18 12:47:42 +08:00
parent a96bde2557
commit c499109668
10 changed files with 202 additions and 0 deletions

View File

@ -16,6 +16,7 @@ import type {
Login,
Logout,
Checkout,
Vendor,
} from './types'
import type { Fetcher, SWRHook, MutationHook } from './utils/types'
@ -62,6 +63,9 @@ export type Provider = CommerceConfig & {
useLogin?: MutationHook<Login.LoginHook>
useLogout?: MutationHook<Logout.LogoutHook>
}
vendors?: {
useVendors?: SWRHook<Vendor.VendorHook>
}
}
export type CommerceConfig = {

View File

@ -8,6 +8,7 @@ import * as Page from './page'
import * as Product from './product'
import * as Signup from './signup'
import * as Site from './site'
import * as Vendor from './vendors'
import * as Wishlist from './wishlist'
export type {
@ -21,5 +22,6 @@ export type {
Product,
Signup,
Site,
Vendor,
Wishlist,
}

View File

@ -0,0 +1,22 @@
// TODO: define this type
export type Vendor = any
export type VendorTypes = {
vendor: Vendor
}
export type VendorHook<T extends VendorTypes = VendorTypes> = {
data: T['vendor'] | null
fetchData: { customer: T['vendor'] } | null
}
export type VendorSchema<T extends VendorTypes = VendorTypes> = {
endpoint: {
options: {}
handlers: {
getLoggedInCustomer: {
data: { customer: T['vendor'] } | null
}
}
}
}

View File

@ -0,0 +1,20 @@
import { useHook, useSWRHook } from '../utils/use-hook'
import { SWRFetcher } from '../utils/default-fetcher'
import type { VendorHook } from '../types/vendors'
import type { HookFetcherFn, SWRHook } from '../utils/types'
import type { Provider } from '..'
export type UseVendors<
H extends SWRHook<VendorHook<any>> = SWRHook<VendorHook>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<VendorHook> = SWRFetcher
const fn = (provider: Provider) => provider.vendors?.useVendors!
const useVendors: UseVendors = (input) => {
const hook = useHook(fn)
return useSWRHook({ fetcher, ...hook })(input)
}
export default useVendors

View File

@ -0,0 +1 @@
export default function noopApi(...args: any[]): void {}

View File

@ -9,6 +9,7 @@ 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 useCheckout } from './checkout/use-checkout'
import { handler as useVendors } from './vendors/use-vendors'
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'
@ -23,6 +24,7 @@ const spreeProvider = {
products: { useSearch },
auth: { useLogin, useLogout, useSignup },
checkout: { useCheckout },
vendors: { useVendors },
wishlist: {
useWishlist,
useAddItem: useWishlistAddItem,

1
packages/spree/src/vendors/index.ts vendored Normal file
View File

@ -0,0 +1 @@
export { default as useVendors } from './use-vendors'

View File

@ -0,0 +1,58 @@
import type { SWRHook } from '@vercel/commerce/utils/types'
import useVendors from '@vercel/commerce/vendors/use-vendors'
import type { Vendor, VendorHook } from '@vercel/commerce/types/vendors'
import type { UseVendors } from '@vercel/commerce/vendors/use-vendors'
import type { GraphQLFetcherResult } from '@vercel/commerce/api'
import { Vendor as IVendor } from '@spree/storefront-api-v2-sdk/types/interfaces/Vendor'
export default useVendors as UseVendors<typeof handler>
export const handler: SWRHook<VendorHook> = {
// Provide fetchOptions for SWR cache key
fetchOptions: {
url: 'vendors',
query: 'list',
},
async fetcher({ input, options, fetch }) {
console.info(
'useVendors fetcher called. Configuration: ',
'input: ',
input,
'options: ',
options
)
const { data: spreeSuccessResponse } = await fetch<
GraphQLFetcherResult<IVendor>
>({
variables: {
methodPath: 'vendors.list',
arguments: [
{},
{
include: 'products',
},
],
},
})
// const normalizedProducts: Vendor[] = spreeSuccessResponse.data.map(
// (spreeVendors) => normalizeProduct(spreeSuccessResponse, spreeVendors)
// )
return { data: spreeSuccessResponse.data, isLoading: !spreeSuccessResponse }
},
useHook: ({ useData }) => {
const useWrappedHook: ReturnType<SWRHook<VendorHook>['useHook']> = (
input
) => {
return useData({
swrOptions: {
revalidateOnFocus: false,
...input?.swrOptions,
},
})
}
return useWrappedHook
},
}

View File

@ -0,0 +1,4 @@
import vendorApi from '@framework/api/endpoints/vendors'
import commerce from '@lib/api/commerce'
export default vendorApi(commerce)

88
site/pages/vendors.tsx Normal file
View File

@ -0,0 +1,88 @@
import type { GetStaticPropsContext } from 'next'
import useVendors from '@framework/vendors/use-vendors'
import commerce from '@lib/api/commerce'
import { Layout } from '@components/common'
import { Container } from '@components/ui'
import { Key, ReactChild, ReactFragment, ReactPortal } from 'react'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = { locale, locales }
const pagesPromise = commerce.getAllPages({ config, preview })
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
const { pages } = await pagesPromise
const { categories } = await siteInfoPromise
return {
props: { pages, categories },
}
}
export default function Vendor() {
const { data, isLoading } = useVendors()
if (isLoading) {
return <div>Loading...</div>
}
return (
<Container>
<div>
<h1>Vendor:</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>About us</th>
<th>Contact us</th>
</tr>
</thead>
<tbody>
{/* TODO Fix type for vendor */}
{data.data.map(
(vendor: {
id: Key | null | undefined
attributes: {
name:
| boolean
| ReactChild
| ReactFragment
| ReactPortal
| null
| undefined
about_us:
| boolean
| ReactChild
| ReactFragment
| ReactPortal
| null
| undefined
contact_us:
| boolean
| ReactChild
| ReactFragment
| ReactPortal
| null
| undefined
}
}) => {
return (
<tr key={vendor.id}>
<td>{vendor.attributes.name}</td>
<td>{vendor.attributes.about_us}</td>
<td>{vendor.attributes.contact_us}</td>
</tr>
)
}
)}
</tbody>
</table>
</div>
</Container>
)
}
Vendor.Layout = Layout