4
0
forked from crowetic/commerce

Added products paths to getStaticPaths

This commit is contained in:
Luis Alvarez 2020-10-01 20:26:32 -05:00
parent ca24a53cbf
commit 390b2c3303
4 changed files with 102 additions and 25 deletions

View File

@ -0,0 +1,54 @@
import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema';
import type { RecursivePartial, RecursiveRequired } from '../utils/types';
import { BigcommerceConfig, getConfig } from '..';
export const getAllProductPathsQuery = /* GraphQL */ `
query getAllProductPaths {
site {
products {
edges {
node {
path
}
}
}
}
}
`;
export interface GetAllProductPathsResult<T> {
products: T extends GetAllProductPathsQuery
? NonNullable<T['site']['products']['edges']>
: unknown;
}
async function getAllProductPaths(opts?: {
query?: string;
config?: BigcommerceConfig;
}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>>;
async function getAllProductPaths<T, V = any>(opts: {
query: string;
config?: BigcommerceConfig;
}): Promise<GetAllProductPathsResult<T>>;
async function getAllProductPaths({
query = getAllProductPathsQuery,
config = getConfig(),
}: {
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;
return {
products: (products as RecursiveRequired<typeof products>) ?? [],
};
}
export default getAllProductPaths;

View File

@ -4,16 +4,11 @@ import type {
} from 'lib/bigcommerce/schema'; } from 'lib/bigcommerce/schema';
import type { RecursivePartial, RecursiveRequired } from '../utils/types'; import type { RecursivePartial, RecursiveRequired } from '../utils/types';
import { productInfoFragment } from '../fragments/product'; import { productInfoFragment } from '../fragments/product';
import { import { BigcommerceConfig, getConfig, Images } from '..';
BigcommerceConfig,
getConfig,
Images,
ProductImageVariables,
} from '..';
export const getProductQuery = /* GraphQL */ ` export const getProductQuery = /* GraphQL */ `
query getProduct( query getProduct(
$slug: String! $path: String!
$imgSmallWidth: Int = 320 $imgSmallWidth: Int = 320
$imgSmallHeight: Int $imgSmallHeight: Int
$imgMediumWidth: Int = 640 $imgMediumWidth: Int = 640
@ -24,7 +19,7 @@ export const getProductQuery = /* GraphQL */ `
$imgXLHeight: Int $imgXLHeight: Int
) { ) {
site { site {
route(path: $slug) { route(path: $path) {
node { node {
__typename __typename
... on Product { ... on Product {
@ -45,7 +40,7 @@ export interface GetProductResult<T> {
} }
export type ProductVariables = Images & export type ProductVariables = Images &
Omit<GetProductQueryVariables, keyof ProductImageVariables>; ({ path: string; slug?: never } | { path?: never; slug: string });
async function getProduct(opts: { async function getProduct(opts: {
query?: string; query?: string;
@ -61,7 +56,7 @@ async function getProduct<T, V = any>(opts: {
async function getProduct({ async function getProduct({
query = getProductQuery, query = getProductQuery,
variables: vars, variables: { slug, ...vars },
config = getConfig(), config = getConfig(),
}: { }: {
query?: string; query?: string;
@ -71,6 +66,7 @@ async function getProduct({
const variables: GetProductQueryVariables = { const variables: GetProductQueryVariables = {
...config.imageVariables, ...config.imageVariables,
...vars, ...vars,
path: slug ? `/${slug}/` : vars.path!,
}; };
const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, { const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, {
variables, variables,

View File

@ -1713,6 +1713,26 @@ export type ProductInfoFragment = (
) } ) }
); );
export type GetAllProductPathsQueryVariables = Exact<{ [key: string]: never; }>;
export type GetAllProductPathsQuery = (
{ __typename?: 'Query' }
& { site: (
{ __typename?: 'Site' }
& { products: (
{ __typename?: 'ProductConnection' }
& { edges?: Maybe<Array<Maybe<(
{ __typename?: 'ProductEdge' }
& { node: (
{ __typename?: 'Product' }
& Pick<Product, 'path'>
) }
)>>> }
) }
) }
);
export type GetAllProductsQueryVariables = Exact<{ export type GetAllProductsQueryVariables = Exact<{
first?: Maybe<Scalars['Int']>; first?: Maybe<Scalars['Int']>;
imgSmallWidth?: Maybe<Scalars['Int']>; imgSmallWidth?: Maybe<Scalars['Int']>;
@ -1748,7 +1768,7 @@ export type GetAllProductsQuery = (
); );
export type GetProductQueryVariables = Exact<{ export type GetProductQueryVariables = Exact<{
slug: Scalars['String']; path: Scalars['String'];
imgSmallWidth?: Maybe<Scalars['Int']>; imgSmallWidth?: Maybe<Scalars['Int']>;
imgSmallHeight?: Maybe<Scalars['Int']>; imgSmallHeight?: Maybe<Scalars['Int']>;
imgMediumWidth?: Maybe<Scalars['Int']>; imgMediumWidth?: Maybe<Scalars['Int']>;

View File

@ -1,18 +1,16 @@
import { GetStaticPropsContext, InferGetStaticPropsType } from "next"; import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
import { useRouter } from "next/router"; import { useRouter } from 'next/router';
import getProduct from "lib/bigcommerce/api/operations/get-product"; import getProduct from 'lib/bigcommerce/api/operations/get-product';
import { Layout } from "@components/core"; import { Layout } from '@components/core';
import { ProductView } from "@components/product"; import { ProductView } from '@components/product';
import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product-paths';
export async function getStaticProps({ export async function getStaticProps({
params, params,
}: GetStaticPropsContext<{ slug: string }>) { }: GetStaticPropsContext<{ slug: string }>) {
const { product } = await getProduct({ variables: { slug: params!.slug } }); const { product } = await getProduct({ variables: { slug: params!.slug } });
console.log("PRODUCT", product);
const productData = { const productData = {
title: "T-Shirt", title: 'T-Shirt',
description: ` description: `
Nothing undercover about this tee. Nope. This is the official Bad Nothing undercover about this tee. Nope. This is the official Bad
Boys tee. Printed in white or black ink on Black, Brown, or Oatmeal. Boys tee. Printed in white or black ink on Black, Brown, or Oatmeal.
@ -21,12 +19,13 @@ export async function getStaticProps({
run. Printing starts when the drop ends. Reminder: Bad Boys For run. Printing starts when the drop ends. Reminder: Bad Boys For
Life. Shipping may take 10+ days due to COVID-19. Life. Shipping may take 10+ days due to COVID-19.
`, `,
price: "$50", price: '$50',
colors: ["black", "white", "pink"], colors: ['black', 'white', 'pink'],
sizes: ["s", "m", "l", "xl", "xxl"], sizes: ['s', 'm', 'l', 'xl', 'xxl'],
}; };
return { return {
props: { props: {
product,
productData, productData,
}, },
revalidate: 200, revalidate: 200,
@ -34,16 +33,24 @@ export async function getStaticProps({
} }
export async function getStaticPaths() { export async function getStaticPaths() {
const { products } = await getAllProductPaths();
return { return {
paths: [], paths: products.map((product) => ({
fallback: "unstable_blocking", params: { slug: product!.node.path },
})),
fallback: 'unstable_blocking',
}; };
} }
export default function Home({ export default function Home({
product,
productData, productData,
}: InferGetStaticPropsType<typeof getStaticProps>) { }: InferGetStaticPropsType<typeof getStaticProps>) {
console.log('PRODUCT', product);
const router = useRouter(); const router = useRouter();
return ( return (
<Layout> <Layout>
{router.isFallback ? ( {router.isFallback ? (