diff --git a/packages/commerce/src/index.tsx b/packages/commerce/src/index.tsx index 8450f1e3e..a401484a5 100644 --- a/packages/commerce/src/index.tsx +++ b/packages/commerce/src/index.tsx @@ -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 useLogout?: MutationHook } + vendors?: { + useVendors?: SWRHook + } } export type CommerceConfig = { diff --git a/packages/commerce/src/types/index.ts b/packages/commerce/src/types/index.ts index 7ab0b7f64..6f273177d 100644 --- a/packages/commerce/src/types/index.ts +++ b/packages/commerce/src/types/index.ts @@ -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, } diff --git a/packages/commerce/src/types/vendors.ts b/packages/commerce/src/types/vendors.ts new file mode 100644 index 000000000..5ebdf5b2f --- /dev/null +++ b/packages/commerce/src/types/vendors.ts @@ -0,0 +1,22 @@ +// TODO: define this type +export type Vendor = any + +export type VendorTypes = { + vendor: Vendor +} + +export type VendorHook = { + data: T['vendor'] | null + fetchData: { customer: T['vendor'] } | null +} + +export type VendorSchema = { + endpoint: { + options: {} + handlers: { + getLoggedInCustomer: { + data: { customer: T['vendor'] } | null + } + } + } +} diff --git a/packages/commerce/src/vendors/use-vendors.tsx b/packages/commerce/src/vendors/use-vendors.tsx new file mode 100644 index 000000000..c681158a2 --- /dev/null +++ b/packages/commerce/src/vendors/use-vendors.tsx @@ -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> = SWRHook +> = ReturnType + +export const fetcher: HookFetcherFn = SWRFetcher + +const fn = (provider: Provider) => provider.vendors?.useVendors! + +const useVendors: UseVendors = (input) => { + const hook = useHook(fn) + return useSWRHook({ fetcher, ...hook })(input) +} + +export default useVendors diff --git a/packages/spree/src/api/endpoints/vendors/index.tsx b/packages/spree/src/api/endpoints/vendors/index.tsx new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/packages/spree/src/api/endpoints/vendors/index.tsx @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/packages/spree/src/provider.ts b/packages/spree/src/provider.ts index de6ddb207..5f52ab760 100644 --- a/packages/spree/src/provider.ts +++ b/packages/spree/src/provider.ts @@ -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, diff --git a/packages/spree/src/vendors/index.ts b/packages/spree/src/vendors/index.ts new file mode 100644 index 000000000..54c54bda2 --- /dev/null +++ b/packages/spree/src/vendors/index.ts @@ -0,0 +1 @@ +export { default as useVendors } from './use-vendors' diff --git a/packages/spree/src/vendors/use-vendors.tsx b/packages/spree/src/vendors/use-vendors.tsx new file mode 100644 index 000000000..3053af3c8 --- /dev/null +++ b/packages/spree/src/vendors/use-vendors.tsx @@ -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 + +export const handler: SWRHook = { + // 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 + >({ + 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['useHook']> = ( + input + ) => { + return useData({ + swrOptions: { + revalidateOnFocus: false, + ...input?.swrOptions, + }, + }) + } + + return useWrappedHook + }, +} diff --git a/site/pages/api/vendors.ts b/site/pages/api/vendors.ts new file mode 100644 index 000000000..9ffd1f08e --- /dev/null +++ b/site/pages/api/vendors.ts @@ -0,0 +1,4 @@ +import vendorApi from '@framework/api/endpoints/vendors' +import commerce from '@lib/api/commerce' + +export default vendorApi(commerce) diff --git a/site/pages/vendors.tsx b/site/pages/vendors.tsx new file mode 100644 index 000000000..c304c7ef3 --- /dev/null +++ b/site/pages/vendors.tsx @@ -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
Loading...
+ } + + return ( + +
+

Vendor:

+ + + + + + + + + + {/* 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 ( + + + + + + ) + } + )} + +
NameAbout usContact us
{vendor.attributes.name}{vendor.attributes.about_us}{vendor.attributes.contact_us}
+
+
+ ) +} + +Vendor.Layout = Layout