forked from crowetic/commerce
Improved types and added method for product
This commit is contained in:
parent
2971b4f802
commit
fdb306a988
@ -1,9 +1,9 @@
|
||||
import {
|
||||
import type {
|
||||
GetAllProductsQuery,
|
||||
GetAllProductsQueryVariables,
|
||||
} from 'lib/bigcommerce/schema';
|
||||
import type { RecursivePartial, RecursiveRequired } from '../types';
|
||||
import { getConfig, Images, ProductImageVariables } from '..';
|
||||
import { RecursivePartial } from '../types';
|
||||
|
||||
export const getAllProductsQuery = /* GraphQL */ `
|
||||
query getAllProducts(
|
||||
@ -104,42 +104,45 @@ export const getAllProductsQuery = /* GraphQL */ `
|
||||
|
||||
export interface GetAllProductsResult<T> {
|
||||
products: T extends GetAllProductsQuery
|
||||
? T['site']['products']['edges']
|
||||
? NonNullable<T['site']['products']['edges']>
|
||||
: unknown;
|
||||
}
|
||||
|
||||
export type ProductVariables = Images &
|
||||
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
||||
|
||||
async function getAllProducts<T, V = any>(opts: {
|
||||
query: string;
|
||||
variables?: V;
|
||||
}): Promise<GetAllProductsResult<T>>;
|
||||
|
||||
async function getAllProducts(opts?: {
|
||||
query?: string;
|
||||
variables?: ProductVariables;
|
||||
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
||||
|
||||
async function getAllProducts<T, V = any>(opts: {
|
||||
query: string;
|
||||
variables?: V;
|
||||
}): Promise<GetAllProductsResult<T>>;
|
||||
|
||||
async function getAllProducts({
|
||||
query = getAllProductsQuery,
|
||||
variables: vars,
|
||||
}: {
|
||||
query?: string;
|
||||
variables?: ProductVariables;
|
||||
} = {}): Promise<GetAllProductsResult<RecursivePartial<GetAllProductsQuery>>> {
|
||||
} = {}): Promise<GetAllProductsResult<GetAllProductsQuery>> {
|
||||
const config = getConfig();
|
||||
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;
|
||||
|
||||
return {
|
||||
products: data?.site?.products?.edges,
|
||||
products: (products as RecursiveRequired<typeof products>) ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
|
131
lib/bigcommerce/api/operations/get-product.ts
Normal file
131
lib/bigcommerce/api/operations/get-product.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import type {
|
||||
GetProductQuery,
|
||||
GetProductQueryVariables,
|
||||
} from 'lib/bigcommerce/schema';
|
||||
import type { RecursivePartial, RecursiveRequired } from '../types';
|
||||
import { getConfig, Images, ProductImageVariables } from '..';
|
||||
|
||||
export const getProductQuery = /* GraphQL */ `
|
||||
query getProduct(
|
||||
$slug: String!
|
||||
$imgSmallWidth: Int = 320
|
||||
$imgSmallHeight: Int
|
||||
$imgMediumWidth: Int = 640
|
||||
$imgMediumHeight: Int
|
||||
$imgLargeWidth: Int = 960
|
||||
$imgLargeHeight: Int
|
||||
$imgXLWidth: Int = 1280
|
||||
$imgXLHeight: Int
|
||||
) {
|
||||
site {
|
||||
route(path: $slug) {
|
||||
node {
|
||||
__typename
|
||||
... on Product {
|
||||
entityId
|
||||
name
|
||||
path
|
||||
brand {
|
||||
name
|
||||
}
|
||||
description
|
||||
prices {
|
||||
price {
|
||||
currencyCode
|
||||
value
|
||||
}
|
||||
salePrice {
|
||||
currencyCode
|
||||
value
|
||||
}
|
||||
}
|
||||
images {
|
||||
edges {
|
||||
node {
|
||||
urlSmall: url(width: $imgSmallWidth, height: $imgSmallHeight)
|
||||
urlMedium: url(
|
||||
width: $imgMediumWidth
|
||||
height: $imgMediumHeight
|
||||
)
|
||||
urlLarge: url(width: $imgLargeWidth, height: $imgLargeHeight)
|
||||
urlXL: url(width: $imgXLWidth, height: $imgXLHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
variants {
|
||||
edges {
|
||||
node {
|
||||
entityId
|
||||
}
|
||||
}
|
||||
}
|
||||
options {
|
||||
edges {
|
||||
node {
|
||||
entityId
|
||||
displayName
|
||||
isRequired
|
||||
values {
|
||||
edges {
|
||||
node {
|
||||
entityId
|
||||
label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export interface GetProductResult<T> {
|
||||
product?: T extends GetProductQuery
|
||||
? Extract<T['site']['route']['node'], { __typename: 'Product' }>
|
||||
: unknown;
|
||||
}
|
||||
|
||||
export type ProductVariables = Images &
|
||||
Omit<GetProductQueryVariables, keyof ProductImageVariables>;
|
||||
|
||||
async function getProduct(opts: {
|
||||
query?: string;
|
||||
variables: ProductVariables;
|
||||
}): Promise<GetProductResult<GetProductQuery>>;
|
||||
|
||||
async function getProduct<T, V = any>(opts: {
|
||||
query: string;
|
||||
variables: V;
|
||||
}): Promise<GetProductResult<T>>;
|
||||
|
||||
async function getProduct({
|
||||
query = getProductQuery,
|
||||
variables: vars,
|
||||
}: {
|
||||
query?: string;
|
||||
variables: ProductVariables;
|
||||
}): Promise<GetProductResult<GetProductQuery>> {
|
||||
const config = getConfig();
|
||||
const variables: GetProductQueryVariables = {
|
||||
...config.imageVariables,
|
||||
...vars,
|
||||
};
|
||||
const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, {
|
||||
variables,
|
||||
});
|
||||
const product = data.site?.route?.node;
|
||||
|
||||
if (product?.__typename === 'Product') {
|
||||
return {
|
||||
product: product as RecursiveRequired<typeof product>,
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
export default getProduct;
|
@ -1,3 +1,7 @@
|
||||
export type RecursivePartial<T> = {
|
||||
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||
};
|
||||
|
||||
export type RecursiveRequired<T> = {
|
||||
[P in keyof T]-?: RecursiveRequired<T[P]>;
|
||||
};
|
||||
|
77
lib/bigcommerce/schema.d.ts
vendored
77
lib/bigcommerce/schema.d.ts
vendored
@ -1736,3 +1736,80 @@ export type GetAllProductsQuery = (
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type GetProductQueryVariables = Exact<{
|
||||
slug: Scalars['String'];
|
||||
imgSmallWidth?: Maybe<Scalars['Int']>;
|
||||
imgSmallHeight?: Maybe<Scalars['Int']>;
|
||||
imgMediumWidth?: Maybe<Scalars['Int']>;
|
||||
imgMediumHeight?: Maybe<Scalars['Int']>;
|
||||
imgLargeWidth?: Maybe<Scalars['Int']>;
|
||||
imgLargeHeight?: Maybe<Scalars['Int']>;
|
||||
imgXLWidth?: Maybe<Scalars['Int']>;
|
||||
imgXLHeight?: Maybe<Scalars['Int']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type GetProductQuery = (
|
||||
{ __typename?: 'Query' }
|
||||
& { site: (
|
||||
{ __typename?: 'Site' }
|
||||
& { route: (
|
||||
{ __typename?: 'Route' }
|
||||
& { node?: Maybe<{ __typename: 'Brand' } | { __typename: 'Category' } | (
|
||||
{ __typename: 'Product' }
|
||||
& Pick<Product, 'entityId' | 'name' | 'path' | 'description'>
|
||||
& { brand?: Maybe<(
|
||||
{ __typename?: 'Brand' }
|
||||
& Pick<Brand, 'name'>
|
||||
)>, prices?: Maybe<(
|
||||
{ __typename?: 'Prices' }
|
||||
& { price: (
|
||||
{ __typename?: 'Money' }
|
||||
& Pick<Money, 'currencyCode' | 'value'>
|
||||
), salePrice?: Maybe<(
|
||||
{ __typename?: 'Money' }
|
||||
& Pick<Money, 'currencyCode' | 'value'>
|
||||
)> }
|
||||
)>, images: (
|
||||
{ __typename?: 'ImageConnection' }
|
||||
& { edges?: Maybe<Array<Maybe<(
|
||||
{ __typename?: 'ImageEdge' }
|
||||
& { node: (
|
||||
{ __typename?: 'Image' }
|
||||
& { urlSmall: Image['url'], urlMedium: Image['url'], urlLarge: Image['url'], urlXL: Image['url'] }
|
||||
) }
|
||||
)>>> }
|
||||
), variants: (
|
||||
{ __typename?: 'VariantConnection' }
|
||||
& { edges?: Maybe<Array<Maybe<(
|
||||
{ __typename?: 'VariantEdge' }
|
||||
& { node: (
|
||||
{ __typename?: 'Variant' }
|
||||
& Pick<Variant, 'entityId'>
|
||||
) }
|
||||
)>>> }
|
||||
), options: (
|
||||
{ __typename?: 'OptionConnection' }
|
||||
& { edges?: Maybe<Array<Maybe<(
|
||||
{ __typename?: 'OptionEdge' }
|
||||
& { node: (
|
||||
{ __typename?: 'ProductOption' }
|
||||
& Pick<ProductOption, 'entityId' | 'displayName' | 'isRequired'>
|
||||
& { values: (
|
||||
{ __typename?: 'OptionValueConnection' }
|
||||
& { edges?: Maybe<Array<Maybe<(
|
||||
{ __typename?: 'OptionValueEdge' }
|
||||
& { node: (
|
||||
{ __typename?: 'ProductOptionValue' }
|
||||
& Pick<ProductOptionValue, 'entityId' | 'label'>
|
||||
) }
|
||||
)>>> }
|
||||
) }
|
||||
) }
|
||||
)>>> }
|
||||
) }
|
||||
) | { __typename: 'Variant' }> }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { Layout } from "@components/core";
|
||||
import { ProductView } from "@components/product";
|
||||
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import getProduct from 'lib/bigcommerce/api/operations/get-product';
|
||||
import { Layout } from '@components/core';
|
||||
import { ProductView } from '@components/product';
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: GetStaticPropsContext<{ slug: string }>) {
|
||||
const { product } = await getProduct({ variables: { slug: params!.slug } });
|
||||
|
||||
console.log('PRODUCT', product);
|
||||
|
||||
export async function getStaticProps() {
|
||||
const productData = {
|
||||
title: "T-Shirt",
|
||||
title: 'T-Shirt',
|
||||
description: `
|
||||
Nothing undercover about this tee. Nope. This is the official Bad
|
||||
Boys tee. Printed in white or black ink on Black, Brown, or Oatmeal.
|
||||
@ -13,9 +21,9 @@ export async function getStaticProps() {
|
||||
run. Printing starts when the drop ends. Reminder: Bad Boys For
|
||||
Life. Shipping may take 10+ days due to COVID-19.
|
||||
`,
|
||||
price: "$50",
|
||||
colors: ["black", "white", "pink"],
|
||||
sizes: ["s", "m", "l", "xl", "xxl"],
|
||||
price: '$50',
|
||||
colors: ['black', 'white', 'pink'],
|
||||
sizes: ['s', 'm', 'l', 'xl', 'xxl'],
|
||||
};
|
||||
return {
|
||||
props: {
|
||||
@ -28,11 +36,13 @@ export async function getStaticProps() {
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [],
|
||||
fallback: "unstable_blocking",
|
||||
fallback: 'unstable_blocking',
|
||||
};
|
||||
}
|
||||
|
||||
export default function Home({ productData }) {
|
||||
export default function Home({
|
||||
productData,
|
||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<Layout>
|
Loading…
x
Reference in New Issue
Block a user