forked from crowetic/commerce
Merge branch 'master' of https://github.com/okbel/e-comm-example
This commit is contained in:
commit
e8e5ce11f5
@ -38,7 +38,7 @@ const CartSidebarView: FunctionComponent = () => {
|
|||||||
<span>-</span>
|
<span>-</span>
|
||||||
<input
|
<input
|
||||||
className="w-6 border-gray-300 border mx-3 rounded text-center text-sm"
|
className="w-6 border-gray-300 border mx-3 rounded text-center text-sm"
|
||||||
value="1"
|
defaultValue="1"
|
||||||
/>
|
/>
|
||||||
<span>+</span>
|
<span>+</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@apply mr-6 cursor-pointer;
|
@apply mr-6 cursor-pointer relative;
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,11 @@ const UserNav: FunctionComponent<Props> = ({ className }) => {
|
|||||||
return (
|
return (
|
||||||
<nav className={rootClassName}>
|
<nav className={rootClassName}>
|
||||||
<ul className={s.list}>
|
<ul className={s.list}>
|
||||||
<li className={s.item}>
|
<li className={s.item} onClick={openSidebar}>
|
||||||
<Bag onClick={openSidebar} />
|
<Bag />
|
||||||
|
<span className="bg-black h-4 w-4 absolute rounded-full inset-3 text-white flex items-center justify-center font-bold text-xs">
|
||||||
|
1
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li className={s.item}>
|
<li className={s.item}>
|
||||||
<Heart />
|
<Heart />
|
||||||
|
@ -4,9 +4,9 @@ const Cross = ({ ...props }) => {
|
|||||||
return (
|
return (
|
||||||
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" {...props}>
|
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" {...props}>
|
||||||
<path
|
<path
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
stroke-linejoin="round"
|
strokeLinejoin="round"
|
||||||
stroke-width="2"
|
strokeWidth="2"
|
||||||
d="M6 18L18 6M6 6l12 12"
|
d="M6 18L18 6M6 6l12 12"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
3
components/product/ProductCard/ProductCard.module.css
Normal file
3
components/product/ProductCard/ProductCard.module.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.root {
|
||||||
|
@apply w-full h-full flex flex-row px-2;
|
||||||
|
}
|
32
components/product/ProductCard/ProductCard.tsx
Normal file
32
components/product/ProductCard/ProductCard.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import cn from "classnames";
|
||||||
|
import s from "./ProductCard.module.css";
|
||||||
|
import React, { FunctionComponent } from "react";
|
||||||
|
import { Heart } from "@components/icon";
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
children?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductCard: FunctionComponent<Props> = ({ className }) => {
|
||||||
|
const rootClassName = cn(s.root, className);
|
||||||
|
return (
|
||||||
|
<div className={rootClassName}>
|
||||||
|
<div className="absolute">
|
||||||
|
<h1 className="px-8 py-2 bg-white text-black font-bold text-3xl">
|
||||||
|
T-Shirt
|
||||||
|
</h1>
|
||||||
|
<div className="px-6 py-2 pb-4 bg-white text-black font-semibold inline-block">
|
||||||
|
$50
|
||||||
|
</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="bg-violet h-full"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductCard;
|
1
components/product/ProductCard/index.ts
Normal file
1
components/product/ProductCard/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ProductCard";
|
4
components/product/ProductGrid/ProductGrid.module.css
Normal file
4
components/product/ProductGrid/ProductGrid.module.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.root {
|
||||||
|
@apply grid grid-cols-1 lg:grid-cols-3 lg:grid-rows-4 w-full h-96;
|
||||||
|
min-height: calc((100vh - 80px - 56px) * 2);
|
||||||
|
}
|
25
components/product/ProductGrid/ProductGrid.tsx
Normal file
25
components/product/ProductGrid/ProductGrid.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import cn from "classnames";
|
||||||
|
import React, { FunctionComponent } from "react";
|
||||||
|
import s from "./ProductGrid.module.css";
|
||||||
|
import ProductCard from "@components/ProductCard";
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
children?: any;
|
||||||
|
products: [any];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductView: FunctionComponent<Props> = ({ products, className }) => {
|
||||||
|
const rootClassName = cn(s.root, className);
|
||||||
|
return (
|
||||||
|
<div className={rootClassName}>
|
||||||
|
<div className="row-span-2 lg:col-span-2 bg-violet h-full"></div>
|
||||||
|
<div className="row-span-1 lg:col-span-1 bg-black h-full"></div>
|
||||||
|
<div className="row-span-1 lg:col-span-1 bg-pink"></div>
|
||||||
|
<div className="row-span-1 lg:col-span-1 bg-black h-full"></div>
|
||||||
|
<div className="row-span-2 lg:col-span-2 bg-blue h-full"></div>
|
||||||
|
<div className="row-span-1 lg:col-span-1 bg-cyan"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductView;
|
1
components/product/ProductGrid/index.ts
Normal file
1
components/product/ProductGrid/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ProductGrid";
|
@ -3,14 +3,6 @@ import React, { FunctionComponent } from "react";
|
|||||||
import s from "./ProductView.module.css";
|
import s from "./ProductView.module.css";
|
||||||
import { Button } from "@components/ui";
|
import { Button } from "@components/ui";
|
||||||
import { Swatch } from "@components/product";
|
import { Swatch } from "@components/product";
|
||||||
import { Colors } from "@components/types";
|
|
||||||
interface ProductData {
|
|
||||||
title: string;
|
|
||||||
price: string;
|
|
||||||
description: string;
|
|
||||||
colors: [Colors];
|
|
||||||
sizes: [string];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -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 "./Swatch.module.css";
|
import s from "./Swatch.module.css";
|
||||||
import { Colors } from "@components/types";
|
import { Colors } from "@components/ui/types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
export { default as ProductView } from "./ProductView";
|
|
||||||
export { default as Swatch } from "./Swatch";
|
export { default as Swatch } from "./Swatch";
|
||||||
|
export { default as ProductView } from "./ProductView";
|
||||||
|
export { default as ProductCard } from "./ProductCard";
|
||||||
|
export { default as ProductGrid } from "./ProductGrid";
|
||||||
|
10
components/product/types.ts
Normal file
10
components/product/types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Colors } from "@components/ui/types";
|
||||||
|
export { Product } from "@lib/bigcommerce";
|
||||||
|
|
||||||
|
// export type ProductData = {
|
||||||
|
// title: string;
|
||||||
|
// price: string;
|
||||||
|
// description: string;
|
||||||
|
// colors: [Colors];
|
||||||
|
// sizes: [string];
|
||||||
|
// };
|
51
components/ui/ClickOutside/ClickOutside.tsx
Normal file
51
components/ui/ClickOutside/ClickOutside.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React, {
|
||||||
|
FunctionComponent,
|
||||||
|
MutableRefObject,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
import { Component } from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export interface ClickOutsideProps {
|
||||||
|
onClickOutside: (e?: MouseEvent) => void;
|
||||||
|
children: React.ReactNode | any;
|
||||||
|
render: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ClickOutside extends Component<ClickOutsideProps> {
|
||||||
|
public domNode: Element | null = null;
|
||||||
|
|
||||||
|
handleRef = (element) => {
|
||||||
|
this.domNode = element;
|
||||||
|
};
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
document.addEventListener("click", this.handleClick, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
document.removeEventListener("mousedown", this.handleClick, true);
|
||||||
|
document.removeEventListener("touchstart", this.handleClick, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public handleClick = (event) => {
|
||||||
|
function hasParent(element, root) {
|
||||||
|
return root && root.contains(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasParent(event.target, this.domNode)) {
|
||||||
|
if (typeof this.props.onClickOutside === "function") {
|
||||||
|
this.props.onClickOutside(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return null;
|
||||||
|
// return this.props.render({
|
||||||
|
// innerRef: this.handleRef,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
1
components/ui/ClickOutside/index.ts
Normal file
1
components/ui/ClickOutside/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ClickOutside";
|
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,10 +1,10 @@
|
|||||||
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
|
import { GetStaticPropsContext, InferGetStaticPropsType } from "next";
|
||||||
import getAllProducts from 'lib/bigcommerce/api/operations/get-all-products';
|
import getAllProducts from "lib/bigcommerce/api/operations/get-all-products";
|
||||||
import { Layout } from '@components/core';
|
import { Layout } from "@components/core";
|
||||||
|
import { ProductGrid } from "@components/product";
|
||||||
|
|
||||||
export async function getStaticProps({ preview }: GetStaticPropsContext) {
|
export async function getStaticProps({ preview }: GetStaticPropsContext) {
|
||||||
const { products } = await getAllProducts();
|
const { products } = await getAllProducts();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { products },
|
props: { products },
|
||||||
};
|
};
|
||||||
@ -13,15 +13,10 @@ export async function getStaticProps({ preview }: GetStaticPropsContext) {
|
|||||||
export default function Home({
|
export default function Home({
|
||||||
products,
|
products,
|
||||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||||
console.log('PRODUCTS', products);
|
console.log("PRODUCTS", products);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="h-full grid grid-cols-1 h-full lg:grid-cols-3 lg:grid-rows-2">
|
<ProductGrid products={products} />
|
||||||
<div className="lg:row-span-2 lg:col-span-2 bg-violet h-full"></div>
|
|
||||||
<div className="lg:row-span-1 lg:col-span-1 bg-black h-full"></div>
|
|
||||||
<div className="lg:row-span-1 lg:col-span-1 bg-pink"></div>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
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";
|
||||||
|
|
||||||
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);
|
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,9 +21,9 @@ 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: {
|
||||||
@ -36,7 +36,7 @@ export async function getStaticProps({
|
|||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
return {
|
return {
|
||||||
paths: [],
|
paths: [],
|
||||||
fallback: 'unstable_blocking',
|
fallback: "unstable_blocking",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -15,6 +15,7 @@ module.exports = {
|
|||||||
violet: "#7928CA",
|
violet: "#7928CA",
|
||||||
pink: "#FF0080",
|
pink: "#FF0080",
|
||||||
cyan: "#50E3C2",
|
cyan: "#50E3C2",
|
||||||
|
blue: "#0070F3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@components/*": ["components/*"],
|
"@lib/*": ["lib/*"],
|
||||||
"@assets/*": ["assets/*"]
|
"@assets/*": ["assets/*"],
|
||||||
|
"@components/*": ["components/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
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