mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
Apply prettier over all files
This commit is contained in:
@@ -5,7 +5,7 @@ export const responsiveImageFragment = /* GraphQL */ `
|
||||
urlLarge: url(width: $imgLargeWidth, height: $imgLargeHeight)
|
||||
urlXL: url(width: $imgXLWidth, height: $imgXLHeight)
|
||||
}
|
||||
`;
|
||||
`
|
||||
|
||||
export const productInfoFragment = /* GraphQL */ `
|
||||
fragment productInfo on Product {
|
||||
@@ -63,4 +63,4 @@ export const productInfoFragment = /* GraphQL */ `
|
||||
}
|
||||
|
||||
${responsiveImageFragment}
|
||||
`;
|
||||
`
|
||||
|
@@ -1,17 +1,17 @@
|
||||
import { CommerceAPIConfig } from 'lib/commerce/api';
|
||||
import { GetAllProductsQueryVariables } from '../schema';
|
||||
import fetchAPI from './utils/fetch-api';
|
||||
import { CommerceAPIConfig } from 'lib/commerce/api'
|
||||
import { GetAllProductsQueryVariables } from '../schema'
|
||||
import fetchAPI from './utils/fetch-api'
|
||||
|
||||
export interface Images {
|
||||
small?: ImageOptions;
|
||||
medium?: ImageOptions;
|
||||
large?: ImageOptions;
|
||||
xl?: ImageOptions;
|
||||
small?: ImageOptions
|
||||
medium?: ImageOptions
|
||||
large?: ImageOptions
|
||||
xl?: ImageOptions
|
||||
}
|
||||
|
||||
export interface ImageOptions {
|
||||
width: number;
|
||||
height?: number;
|
||||
width: number
|
||||
height?: number
|
||||
}
|
||||
|
||||
export type ProductImageVariables = Pick<
|
||||
@@ -24,39 +24,39 @@ export type ProductImageVariables = Pick<
|
||||
| 'imgLargeHeight'
|
||||
| 'imgXLWidth'
|
||||
| 'imgXLHeight'
|
||||
>;
|
||||
>
|
||||
|
||||
export interface BigcommerceConfigOptions extends CommerceAPIConfig {
|
||||
images?: Images;
|
||||
images?: Images
|
||||
}
|
||||
|
||||
export interface BigcommerceConfig extends BigcommerceConfigOptions {
|
||||
readonly imageVariables?: ProductImageVariables;
|
||||
readonly imageVariables?: ProductImageVariables
|
||||
}
|
||||
|
||||
const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL;
|
||||
const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN;
|
||||
const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL
|
||||
const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN
|
||||
|
||||
if (!API_URL) {
|
||||
throw new Error(
|
||||
`The environment variable BIGCOMMERCE_STOREFRONT_API_URL is missing and it's required to access your store`
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
if (!API_TOKEN) {
|
||||
throw new Error(
|
||||
`The environment variable BIGCOMMERCE_STOREFRONT_API_TOKEN is missing and it's required to access your store`
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export class Config {
|
||||
private config: BigcommerceConfig;
|
||||
private config: BigcommerceConfig
|
||||
|
||||
constructor(config: BigcommerceConfigOptions) {
|
||||
this.config = {
|
||||
...config,
|
||||
get imageVariables() {
|
||||
const { images } = this;
|
||||
const { images } = this
|
||||
return images
|
||||
? {
|
||||
imgSmallWidth: images.small?.width,
|
||||
@@ -68,17 +68,17 @@ export class Config {
|
||||
imgXLWidth: images.xl?.height,
|
||||
imgXLHeight: images.xl?.height,
|
||||
}
|
||||
: undefined;
|
||||
: undefined
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.config;
|
||||
return this.config
|
||||
}
|
||||
|
||||
setConfig(newConfig: Partial<BigcommerceConfig>) {
|
||||
Object.assign(this.config, newConfig);
|
||||
Object.assign(this.config, newConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,12 +86,12 @@ const config = new Config({
|
||||
commerceUrl: API_URL,
|
||||
apiToken: API_TOKEN,
|
||||
fetch: fetchAPI,
|
||||
});
|
||||
})
|
||||
|
||||
export function getConfig() {
|
||||
return config.getConfig();
|
||||
return config.getConfig()
|
||||
}
|
||||
|
||||
export function setConfig(newConfig: Partial<BigcommerceConfig>) {
|
||||
return config.setConfig(newConfig);
|
||||
return config.setConfig(newConfig)
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema';
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types';
|
||||
import { BigcommerceConfig, getConfig } from '..';
|
||||
import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import { BigcommerceConfig, getConfig } from '..'
|
||||
|
||||
export const getAllProductPathsQuery = /* GraphQL */ `
|
||||
query getAllProductPaths {
|
||||
@@ -14,41 +14,41 @@ export const getAllProductPathsQuery = /* GraphQL */ `
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`
|
||||
|
||||
export interface GetAllProductPathsResult<T> {
|
||||
products: T extends GetAllProductPathsQuery
|
||||
? NonNullable<T['site']['products']['edges']>
|
||||
: unknown;
|
||||
: unknown
|
||||
}
|
||||
|
||||
async function getAllProductPaths(opts?: {
|
||||
query?: string;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>>;
|
||||
query?: string
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>>
|
||||
|
||||
async function getAllProductPaths<T, V = any>(opts: {
|
||||
query: string;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetAllProductPathsResult<T>>;
|
||||
query: string
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetAllProductPathsResult<T>>
|
||||
|
||||
async function getAllProductPaths({
|
||||
query = getAllProductPathsQuery,
|
||||
config = getConfig(),
|
||||
}: {
|
||||
query?: string;
|
||||
config?: BigcommerceConfig;
|
||||
query?: string
|
||||
config?: BigcommerceConfig
|
||||
} = {}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>> {
|
||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||
// required in case there's a custom `query`
|
||||
const data = await config.fetch<RecursivePartial<GetAllProductPathsQuery>>(
|
||||
query
|
||||
);
|
||||
const products = data.site?.products?.edges;
|
||||
)
|
||||
const products = data.site?.products?.edges
|
||||
|
||||
return {
|
||||
products: (products as RecursiveRequired<typeof products>) ?? [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default getAllProductPaths;
|
||||
export default getAllProductPaths
|
||||
|
@@ -1,15 +1,10 @@
|
||||
import type {
|
||||
GetAllProductsQuery,
|
||||
GetAllProductsQueryVariables,
|
||||
} from 'lib/bigcommerce/schema';
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types';
|
||||
import { productInfoFragment } from '../fragments/product';
|
||||
import {
|
||||
BigcommerceConfig,
|
||||
getConfig,
|
||||
Images,
|
||||
ProductImageVariables,
|
||||
} from '..';
|
||||
} from 'lib/bigcommerce/schema'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import { productInfoFragment } from '../fragments/product'
|
||||
import { BigcommerceConfig, getConfig, Images, ProductImageVariables } from '..'
|
||||
|
||||
export const getAllProductsQuery = /* GraphQL */ `
|
||||
query getAllProducts(
|
||||
@@ -40,53 +35,53 @@ export const getAllProductsQuery = /* GraphQL */ `
|
||||
}
|
||||
|
||||
${productInfoFragment}
|
||||
`;
|
||||
`
|
||||
|
||||
export interface GetAllProductsResult<T> {
|
||||
products: T extends GetAllProductsQuery
|
||||
? NonNullable<T['site']['products']['edges']>
|
||||
: unknown;
|
||||
: unknown
|
||||
}
|
||||
|
||||
export type ProductVariables = Images &
|
||||
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
||||
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>
|
||||
|
||||
async function getAllProducts(opts?: {
|
||||
query?: string;
|
||||
variables?: ProductVariables;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
||||
query?: string
|
||||
variables?: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetAllProductsResult<GetAllProductsQuery>>
|
||||
|
||||
async function getAllProducts<T, V = any>(opts: {
|
||||
query: string;
|
||||
variables?: V;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetAllProductsResult<T>>;
|
||||
query: string
|
||||
variables?: V
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetAllProductsResult<T>>
|
||||
|
||||
async function getAllProducts({
|
||||
query = getAllProductsQuery,
|
||||
variables: vars,
|
||||
config = getConfig(),
|
||||
}: {
|
||||
query?: string;
|
||||
variables?: ProductVariables;
|
||||
config?: BigcommerceConfig;
|
||||
query?: string
|
||||
variables?: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
} = {}): Promise<GetAllProductsResult<GetAllProductsQuery>> {
|
||||
const variables: GetAllProductsQueryVariables = {
|
||||
...config.imageVariables,
|
||||
...vars,
|
||||
};
|
||||
}
|
||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||
// required in case there's a custom `query`
|
||||
const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
||||
query,
|
||||
{ variables }
|
||||
);
|
||||
const products = data.site?.products?.edges;
|
||||
)
|
||||
const products = data.site?.products?.edges
|
||||
|
||||
return {
|
||||
products: (products as RecursiveRequired<typeof products>) ?? [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default getAllProducts;
|
||||
export default getAllProducts
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import type {
|
||||
GetProductQuery,
|
||||
GetProductQueryVariables,
|
||||
} from 'lib/bigcommerce/schema';
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types';
|
||||
import { productInfoFragment } from '../fragments/product';
|
||||
import { BigcommerceConfig, getConfig, Images } from '..';
|
||||
} from 'lib/bigcommerce/schema'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import { productInfoFragment } from '../fragments/product'
|
||||
import { BigcommerceConfig, getConfig, Images } from '..'
|
||||
|
||||
export const getProductQuery = /* GraphQL */ `
|
||||
query getProduct(
|
||||
@@ -31,55 +31,55 @@ export const getProductQuery = /* GraphQL */ `
|
||||
}
|
||||
|
||||
${productInfoFragment}
|
||||
`;
|
||||
`
|
||||
|
||||
export interface GetProductResult<T> {
|
||||
product?: T extends GetProductQuery
|
||||
? Extract<T['site']['route']['node'], { __typename: 'Product' }>
|
||||
: unknown;
|
||||
: unknown
|
||||
}
|
||||
|
||||
export type ProductVariables = Images &
|
||||
({ path: string; slug?: never } | { path?: never; slug: string });
|
||||
({ path: string; slug?: never } | { path?: never; slug: string })
|
||||
|
||||
async function getProduct(opts: {
|
||||
query?: string;
|
||||
variables: ProductVariables;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetProductResult<GetProductQuery>>;
|
||||
query?: string
|
||||
variables: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetProductResult<GetProductQuery>>
|
||||
|
||||
async function getProduct<T, V = any>(opts: {
|
||||
query: string;
|
||||
variables: V;
|
||||
config?: BigcommerceConfig;
|
||||
}): Promise<GetProductResult<T>>;
|
||||
query: string
|
||||
variables: V
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetProductResult<T>>
|
||||
|
||||
async function getProduct({
|
||||
query = getProductQuery,
|
||||
variables: { slug, ...vars },
|
||||
config = getConfig(),
|
||||
}: {
|
||||
query?: string;
|
||||
variables: ProductVariables;
|
||||
config?: BigcommerceConfig;
|
||||
query?: string
|
||||
variables: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<GetProductResult<GetProductQuery>> {
|
||||
const variables: GetProductQueryVariables = {
|
||||
...config.imageVariables,
|
||||
...vars,
|
||||
path: slug ? `/${slug}/` : vars.path!,
|
||||
};
|
||||
}
|
||||
const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, {
|
||||
variables,
|
||||
});
|
||||
const product = data.site?.route?.node;
|
||||
})
|
||||
const product = data.site?.route?.node
|
||||
|
||||
if (product?.__typename === 'Product') {
|
||||
return {
|
||||
product: product as RecursiveRequired<typeof product>,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
export default getProduct;
|
||||
export default getProduct
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { CommerceAPIFetchOptions } from 'lib/commerce/api';
|
||||
import { getConfig } from '..';
|
||||
import { CommerceAPIFetchOptions } from 'lib/commerce/api'
|
||||
import { getConfig } from '..'
|
||||
|
||||
export default async function fetchAPI<Q, V = any>(
|
||||
query: string,
|
||||
{ variables, preview }: CommerceAPIFetchOptions<V> = {}
|
||||
): Promise<Q> {
|
||||
const config = getConfig();
|
||||
const config = getConfig()
|
||||
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -16,12 +16,12 @@ export default async function fetchAPI<Q, V = any>(
|
||||
query,
|
||||
variables,
|
||||
}),
|
||||
});
|
||||
})
|
||||
|
||||
const json = await res.json();
|
||||
const json = await res.json()
|
||||
if (json.errors) {
|
||||
console.error(json.errors);
|
||||
throw new Error('Failed to fetch API');
|
||||
console.error(json.errors)
|
||||
throw new Error('Failed to fetch API')
|
||||
}
|
||||
return json.data;
|
||||
return json.data
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
export type RecursivePartial<T> = {
|
||||
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||
};
|
||||
[P in keyof T]?: RecursivePartial<T[P]>
|
||||
}
|
||||
|
||||
export type RecursiveRequired<T> = {
|
||||
[P in keyof T]-?: RecursiveRequired<T[P]>;
|
||||
};
|
||||
[P in keyof T]-?: RecursiveRequired<T[P]>
|
||||
}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import {
|
||||
CartProvider as CommerceCartProvider,
|
||||
useCart as useCommerceCart,
|
||||
} from 'lib/commerce/cart';
|
||||
} from 'lib/commerce/cart'
|
||||
|
||||
export type Cart = any;
|
||||
export type Cart = any
|
||||
|
||||
export function CartProvider({ children }) {
|
||||
return <CommerceCartProvider>{children}</CommerceCartProvider>;
|
||||
return <CommerceCartProvider>{children}</CommerceCartProvider>
|
||||
}
|
||||
|
||||
export function useCart() {
|
||||
return useCommerceCart<Cart>();
|
||||
return useCommerceCart<Cart>()
|
||||
}
|
||||
|
@@ -2,38 +2,38 @@ import {
|
||||
CommerceProvider as CoreCommerceProvider,
|
||||
Connector,
|
||||
useCommerce as useCoreCommerce,
|
||||
} from 'lib/commerce';
|
||||
} from 'lib/commerce'
|
||||
|
||||
async function getText(res: Response) {
|
||||
try {
|
||||
return (await res.text()) || res.statusText;
|
||||
return (await res.text()) || res.statusText
|
||||
} catch (error) {
|
||||
return res.statusText;
|
||||
return res.statusText
|
||||
}
|
||||
}
|
||||
|
||||
async function getError(res: Response) {
|
||||
if (res.headers.get('Content-Type')?.includes('application/json')) {
|
||||
const data = await res.json();
|
||||
return data.errors[0];
|
||||
const data = await res.json()
|
||||
return data.errors[0]
|
||||
}
|
||||
return { message: await getText(res) };
|
||||
return { message: await getText(res) }
|
||||
}
|
||||
|
||||
async function fetcher(url: string, query: string) {
|
||||
const res = await fetch(url);
|
||||
const res = await fetch(url)
|
||||
|
||||
if (res.ok) {
|
||||
return res.json();
|
||||
return res.json()
|
||||
}
|
||||
|
||||
throw await getError(res);
|
||||
throw await getError(res)
|
||||
}
|
||||
|
||||
export const bigcommerce: Connector = {
|
||||
locale: 'en-us',
|
||||
fetcher,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: The connector should be extendable when a developer is using it
|
||||
export function CommerceProvider({ children }) {
|
||||
@@ -41,7 +41,7 @@ export function CommerceProvider({ children }) {
|
||||
<CoreCommerceProvider connector={bigcommerce}>
|
||||
{children}
|
||||
</CoreCommerceProvider>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export const useCommerce = () => useCoreCommerce();
|
||||
export const useCommerce = () => useCoreCommerce()
|
||||
|
84
lib/cart.js
84
lib/cart.js
@@ -1,105 +1,105 @@
|
||||
import { useState, useCallback } from "react";
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { useState, useCallback } from 'react'
|
||||
import useSWR, { mutate } from 'swr'
|
||||
|
||||
async function getText(res) {
|
||||
try {
|
||||
return (await res.text()) || res.statusText;
|
||||
return (await res.text()) || res.statusText
|
||||
} catch (error) {
|
||||
return res.statusText;
|
||||
return res.statusText
|
||||
}
|
||||
}
|
||||
|
||||
async function getError(res) {
|
||||
if (res.headers.get("Content-Type")?.includes("application/json")) {
|
||||
const data = await res.json();
|
||||
return data.errors[0];
|
||||
if (res.headers.get('Content-Type')?.includes('application/json')) {
|
||||
const data = await res.json()
|
||||
return data.errors[0]
|
||||
}
|
||||
return { message: await getText(res) };
|
||||
return { message: await getText(res) }
|
||||
}
|
||||
|
||||
async function fetcher(url) {
|
||||
const res = await fetch(url);
|
||||
const res = await fetch(url)
|
||||
|
||||
if (res.status === 200) {
|
||||
return res.json();
|
||||
return res.json()
|
||||
}
|
||||
throw await getError(res);
|
||||
throw await getError(res)
|
||||
}
|
||||
|
||||
export function useCart() {
|
||||
return useSWR("/api/cart", fetcher);
|
||||
return useSWR('/api/cart', fetcher)
|
||||
}
|
||||
|
||||
export function useAddToCart() {
|
||||
const [{ addingToCart, error }, setStatus] = useState({
|
||||
addingToCart: false,
|
||||
});
|
||||
})
|
||||
const addToCart = useCallback(async ({ product }) => {
|
||||
setStatus({ addingToCart: true });
|
||||
setStatus({ addingToCart: true })
|
||||
|
||||
const res = await fetch("/api/cart", {
|
||||
method: "POST",
|
||||
const res = await fetch('/api/cart', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ product }),
|
||||
});
|
||||
})
|
||||
|
||||
// Product added as expected
|
||||
if (res.status === 200) {
|
||||
setStatus({ addingToCart: false });
|
||||
return mutate("/api/cart");
|
||||
setStatus({ addingToCart: false })
|
||||
return mutate('/api/cart')
|
||||
}
|
||||
|
||||
const error = await getError(res);
|
||||
const error = await getError(res)
|
||||
|
||||
console.error("Adding product to cart failed with:", res.status, error);
|
||||
setStatus({ addingToCart: false, error });
|
||||
}, []);
|
||||
console.error('Adding product to cart failed with:', res.status, error)
|
||||
setStatus({ addingToCart: false, error })
|
||||
}, [])
|
||||
|
||||
return { addToCart, addingToCart, error };
|
||||
return { addToCart, addingToCart, error }
|
||||
}
|
||||
|
||||
export function useUpdateCart() {
|
||||
const [{ updatingCart, error }, setStatus] = useState({
|
||||
updatingCart: false,
|
||||
});
|
||||
})
|
||||
const updateCart = useCallback(async ({ product, item }) => {
|
||||
setStatus({ updatingCart: true });
|
||||
setStatus({ updatingCart: true })
|
||||
|
||||
const res = await fetch(
|
||||
`/api/cart?itemId=${item.id}`,
|
||||
product.quantity < 1
|
||||
? { method: "DELETE" }
|
||||
? { method: 'DELETE' }
|
||||
: {
|
||||
method: "PUT",
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ product }),
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
// Product updated as expected
|
||||
if (res.status === 200) {
|
||||
setStatus({ updatingCart: false });
|
||||
return mutate("/api/cart");
|
||||
setStatus({ updatingCart: false })
|
||||
return mutate('/api/cart')
|
||||
}
|
||||
|
||||
const error = await getError(res);
|
||||
const error = await getError(res)
|
||||
|
||||
console.error("Update to cart failed with:", res.status, error);
|
||||
setStatus({ updatingCart: false, error });
|
||||
}, []);
|
||||
console.error('Update to cart failed with:', res.status, error)
|
||||
setStatus({ updatingCart: false, error })
|
||||
}, [])
|
||||
|
||||
return { updateCart, updatingCart, error };
|
||||
return { updateCart, updatingCart, error }
|
||||
}
|
||||
|
||||
export function useRemoveFromCart() {
|
||||
const { updateCart, updatingCart, error } = useUpdateCart();
|
||||
const { updateCart, updatingCart, error } = useUpdateCart()
|
||||
const removeFromCart = async ({ item }) => {
|
||||
updateCart({ item, product: { quantity: 0 } });
|
||||
};
|
||||
updateCart({ item, product: { quantity: 0 } })
|
||||
}
|
||||
|
||||
return { removeFromCart, removingFromCart: updatingCart, error };
|
||||
return { removeFromCart, removingFromCart: updatingCart, error }
|
||||
}
|
||||
|
@@ -1,15 +1,15 @@
|
||||
export interface CommerceAPIConfig {
|
||||
commerceUrl: string;
|
||||
apiToken: string;
|
||||
commerceUrl: string
|
||||
apiToken: string
|
||||
fetch<Q, V = any>(
|
||||
query: string,
|
||||
queryData?: CommerceAPIFetchOptions<V>
|
||||
): Promise<Q>;
|
||||
): Promise<Q>
|
||||
}
|
||||
|
||||
export interface CommerceAPIFetchOptions<V> {
|
||||
variables?: V;
|
||||
preview?: boolean;
|
||||
variables?: V
|
||||
preview?: boolean
|
||||
}
|
||||
|
||||
// TODO: define interfaces for all the available operations
|
||||
|
@@ -1,37 +1,37 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
import useSWR, { responseInterface } from 'swr';
|
||||
import { useCommerce } from '.';
|
||||
import { createContext, useContext } from 'react'
|
||||
import useSWR, { responseInterface } from 'swr'
|
||||
import { useCommerce } from '.'
|
||||
|
||||
export type Cart = any;
|
||||
export type Cart = any
|
||||
|
||||
export type CartResponse<C extends Cart> = responseInterface<C, Error> & {
|
||||
isEmpty: boolean;
|
||||
};
|
||||
isEmpty: boolean
|
||||
}
|
||||
|
||||
const CartContext = createContext<CartResponse<Cart>>(null);
|
||||
const CartContext = createContext<CartResponse<Cart>>(null)
|
||||
|
||||
function getCartCookie() {
|
||||
// TODO: Figure how the cart should be persisted
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
export function CartProvider({ children }) {
|
||||
const { hooks, fetcher } = useCommerce<Cart>();
|
||||
const { useCart } = hooks;
|
||||
const cartId = getCartCookie();
|
||||
const { hooks, fetcher } = useCommerce<Cart>()
|
||||
const { useCart } = hooks
|
||||
const cartId = getCartCookie()
|
||||
const response = useSWR(
|
||||
() => (cartId ? [useCart.url, useCart.query, useCart.resolver] : null),
|
||||
fetcher
|
||||
);
|
||||
const isEmpty = true;
|
||||
)
|
||||
const isEmpty = true
|
||||
|
||||
return (
|
||||
<CartContext.Provider value={{ ...response, isEmpty }}>
|
||||
{children}
|
||||
</CartContext.Provider>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export function useCart<C extends Cart>() {
|
||||
return useContext(CartContext) as CartResponse<C>;
|
||||
return useContext(CartContext) as CartResponse<C>
|
||||
}
|
||||
|
@@ -1,29 +1,29 @@
|
||||
import { createContext, ReactNode, useContext } from 'react';
|
||||
import { createContext, ReactNode, useContext } from 'react'
|
||||
|
||||
const Commerce = createContext<Connector>(null);
|
||||
const Commerce = createContext<Connector>(null)
|
||||
|
||||
export type CommerceProps = {
|
||||
children?: ReactNode;
|
||||
connector: Connector;
|
||||
};
|
||||
children?: ReactNode
|
||||
connector: Connector
|
||||
}
|
||||
|
||||
export type Connector = {
|
||||
fetcher: Fetcher<any>;
|
||||
locale: string;
|
||||
};
|
||||
fetcher: Fetcher<any>
|
||||
locale: string
|
||||
}
|
||||
|
||||
export type Fetcher<T> = (...args: any) => T | Promise<T>;
|
||||
export type Fetcher<T> = (...args: any) => T | Promise<T>
|
||||
|
||||
export function CommerceProvider({ children, connector }: CommerceProps) {
|
||||
if (!connector) {
|
||||
throw new Error(
|
||||
'CommerceProvider requires a valid headless commerce connector'
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return <Commerce.Provider value={connector}>{children}</Commerce.Provider>;
|
||||
return <Commerce.Provider value={connector}>{children}</Commerce.Provider>
|
||||
}
|
||||
|
||||
export function useCommerce<T extends Connector>() {
|
||||
return useContext(Commerce) as T;
|
||||
return useContext(Commerce) as T
|
||||
}
|
||||
|
Reference in New Issue
Block a user