forked from crowetic/commerce
Changes/ Stable
This commit is contained in:
commit
1c833447ea
@ -1,3 +1,3 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply flex flex-row px-2;
|
@apply w-full h-full flex flex-row px-2;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import s from "./ProductCard.module.css";
|
import s from "./ProductCard.module.css";
|
||||||
import React, { FunctionComponent } from "react";
|
import React, { FunctionComponent } from "react";
|
||||||
|
import { Heart } from "@components/icon";
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: any;
|
children?: any;
|
||||||
@ -12,13 +12,16 @@ const ProductCard: FunctionComponent<Props> = ({ className }) => {
|
|||||||
return (
|
return (
|
||||||
<div className={rootClassName}>
|
<div className={rootClassName}>
|
||||||
<div className="absolute">
|
<div className="absolute">
|
||||||
<h1 className="px-8 py-2 bg-violet text-white font-bold text-3xl">
|
<h1 className="px-8 py-2 bg-white text-black font-bold text-3xl">
|
||||||
{/* {productData.title} */}
|
T-Shirt
|
||||||
</h1>
|
</h1>
|
||||||
<div className="px-6 py-2 pb-4 bg-violet text-white font-semibold inline-block">
|
<div className="px-6 py-2 pb-4 bg-white text-black font-semibold inline-block">
|
||||||
{/* {productData.price} */}
|
$50
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="absolute flex items-center justify-center h-12 w-12 bg-white text-black">
|
||||||
|
<Heart />
|
||||||
|
</div>
|
||||||
<div className="flex-1 h-full p-24">
|
<div className="flex-1 h-full p-24">
|
||||||
<div className="bg-violet h-full"></div>
|
<div className="bg-violet h-full"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import React, { FunctionComponent } from "react";
|
import React, { FunctionComponent } from "react";
|
||||||
import s from "./ProductGrid.module.css";
|
import s from "./ProductGrid.module.css";
|
||||||
|
import ProductCard from "@components/ProductCard";
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: any;
|
children?: any;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import type {
|
||||||
GetAllProductsQuery,
|
GetAllProductsQuery,
|
||||||
GetAllProductsQueryVariables,
|
GetAllProductsQueryVariables,
|
||||||
} from "lib/bigcommerce/schema";
|
} from "lib/bigcommerce/schema";
|
||||||
|
import type { RecursivePartial, RecursiveRequired } from "../types";
|
||||||
import { getConfig, Images, ProductImageVariables } from "..";
|
import { getConfig, Images, ProductImageVariables } from "..";
|
||||||
import { RecursivePartial } from "../types";
|
|
||||||
|
|
||||||
export const getAllProductsQuery = /* GraphQL */ `
|
export const getAllProductsQuery = /* GraphQL */ `
|
||||||
query getAllProducts(
|
query getAllProducts(
|
||||||
@ -104,42 +104,45 @@ export const getAllProductsQuery = /* GraphQL */ `
|
|||||||
|
|
||||||
export interface GetAllProductsResult<T> {
|
export interface GetAllProductsResult<T> {
|
||||||
products: T extends GetAllProductsQuery
|
products: T extends GetAllProductsQuery
|
||||||
? T["site"]["products"]["edges"]
|
? NonNullable<T["site"]["products"]["edges"]>
|
||||||
: unknown;
|
: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProductVariables = Images &
|
export type ProductVariables = Images &
|
||||||
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
||||||
|
|
||||||
async function getAllProducts<T, V = any>(opts: {
|
|
||||||
query: string;
|
|
||||||
variables?: V;
|
|
||||||
}): Promise<GetAllProductsResult<T>>;
|
|
||||||
|
|
||||||
async function getAllProducts(opts?: {
|
async function getAllProducts(opts?: {
|
||||||
query?: string;
|
query?: string;
|
||||||
variables?: ProductVariables;
|
variables?: ProductVariables;
|
||||||
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
||||||
|
|
||||||
|
async function getAllProducts<T, V = any>(opts: {
|
||||||
|
query: string;
|
||||||
|
variables?: V;
|
||||||
|
}): Promise<GetAllProductsResult<T>>;
|
||||||
|
|
||||||
async function getAllProducts({
|
async function getAllProducts({
|
||||||
query = getAllProductsQuery,
|
query = getAllProductsQuery,
|
||||||
variables: vars,
|
variables: vars,
|
||||||
}: {
|
}: {
|
||||||
query?: string;
|
query?: string;
|
||||||
variables?: ProductVariables;
|
variables?: ProductVariables;
|
||||||
} = {}): Promise<GetAllProductsResult<RecursivePartial<GetAllProductsQuery>>> {
|
} = {}): Promise<GetAllProductsResult<GetAllProductsQuery>> {
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
const variables: GetAllProductsQueryVariables = {
|
const variables: GetAllProductsQueryVariables = {
|
||||||
...config.imageVariables,
|
...config.imageVariables,
|
||||||
...vars,
|
...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>>(
|
const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
||||||
query,
|
query,
|
||||||
{ variables }
|
{ variables }
|
||||||
);
|
);
|
||||||
|
const products = data.site?.products?.edges;
|
||||||
|
|
||||||
return {
|
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> = {
|
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]>;
|
||||||
|
};
|
||||||
|
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' }> }
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
6710
package-lock.json
generated
6710
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@
|
|||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"next": "^9.5.4-canary.20",
|
"next": "^9.5.4-canary.20",
|
||||||
"postcss-nested": "^5.0.0",
|
"postcss-nested": "^5.0.1",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"swr": "^0.3.3"
|
"swr": "^0.3.3"
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
|
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 { Layout } from "@components/core";
|
import { Layout } from "@components/core";
|
||||||
import { ProductView } from "@components/product";
|
import { ProductView } from "@components/product";
|
||||||
|
|
||||||
export async function getStaticProps() {
|
export async function getStaticProps({
|
||||||
|
params,
|
||||||
|
}: GetStaticPropsContext<{ slug: string }>) {
|
||||||
|
const { product } = await getProduct({ variables: { slug: params!.slug } });
|
||||||
|
|
||||||
|
console.log("PRODUCT", product);
|
||||||
|
|
||||||
const productData = {
|
const productData = {
|
||||||
title: "T-Shirt",
|
title: "T-Shirt",
|
||||||
description: `
|
description: `
|
||||||
@ -32,7 +40,9 @@ export async function getStaticPaths() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home({ productData }) {
|
export default function Home({
|
||||||
|
productData,
|
||||||
|
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
@ -1,16 +1,16 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
'tailwindcss',
|
"tailwindcss",
|
||||||
'postcss-flexbugs-fixes',
|
"postcss-flexbugs-fixes",
|
||||||
[
|
[
|
||||||
'postcss-preset-env',
|
"postcss-preset-env",
|
||||||
{
|
{
|
||||||
autoprefixer: {
|
autoprefixer: {
|
||||||
flexbox: 'no-2009',
|
flexbox: "no-2009",
|
||||||
},
|
},
|
||||||
stage: 3,
|
stage: 3,
|
||||||
features: {
|
features: {
|
||||||
'custom-properties': false,
|
"custom-properties": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
20
yarn.lock
20
yarn.lock
@ -5712,12 +5712,12 @@ postcss-nested@^4.1.1:
|
|||||||
postcss "^7.0.32"
|
postcss "^7.0.32"
|
||||||
postcss-selector-parser "^6.0.2"
|
postcss-selector-parser "^6.0.2"
|
||||||
|
|
||||||
postcss-nested@^5.0.0:
|
postcss-nested@^5.0.1:
|
||||||
version "5.0.0"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.0.tgz#0d05bb93578ec42919bdbda7d4eb419d5f58fe07"
|
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.1.tgz#e7a77f7a806a09c8de0f2c163d8e3d09f00f3139"
|
||||||
integrity sha512-jQVUwMOkDJPHyY1o3bxLErHnxIFsO3yDgdDsL/rjSkUHrWNdtNGhP50O0P+vUjEwPo+ekCRhLXTe8TziARoS0w==
|
integrity sha512-ZHNSAoHrMtbEzjq+Qs4R0gHijpXc6F1YUv4TGmGaz7rtfMvVJBbu5hMOH+CrhEaljQpEmx5N/P8i1pXTkbVAmg==
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss-selector-parser "^6.0.2"
|
postcss-selector-parser "^6.0.4"
|
||||||
|
|
||||||
postcss-nesting@^7.0.0:
|
postcss-nesting@^7.0.0:
|
||||||
version "7.0.1"
|
version "7.0.1"
|
||||||
@ -5848,6 +5848,16 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
|
|||||||
uniq "^1.0.1"
|
uniq "^1.0.1"
|
||||||
util-deprecate "^1.0.2"
|
util-deprecate "^1.0.2"
|
||||||
|
|
||||||
|
postcss-selector-parser@^6.0.4:
|
||||||
|
version "6.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
|
||||||
|
integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
|
||||||
|
dependencies:
|
||||||
|
cssesc "^3.0.0"
|
||||||
|
indexes-of "^1.0.1"
|
||||||
|
uniq "^1.0.1"
|
||||||
|
util-deprecate "^1.0.2"
|
||||||
|
|
||||||
postcss-value-parser@^3.3.0:
|
postcss-value-parser@^3.3.0:
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user