Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
chigoKawa committed Feb 7, 2022
1 parent a7c92d8 commit f90aa69
Show file tree
Hide file tree
Showing 21 changed files with 4,979 additions and 164 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local
.env

# vercel
.vercel
5 changes: 5 additions & 0 deletions .penv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
NEXT_PUBLIC_SPACE_ID='hg94h980vf1n
NEXT_PUBLIC_DELIVERY_TOKEN='12123123123213'
NEXT_PUBLIC_PREVIEW_TOKEN='123123123213213'
NEXT_PUBLIC_PREVIEW_SECRET='testing'
NEXT_PUBLIC_ENVIRONMENT='slave'
41 changes: 14 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
# Jumpstart shop demo

## Getting Started
# Requirements

First, run the development server:
- Node.js
- Contentful API keys

```bash
npm run dev
# or
yarn dev
```
# Step 1

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Create an empty space in Contentful and note the API keys (delivery, preview and management).
From the Contentful web app go to SPACE SETTINGS --> API keys....

You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
# Step 2
After downloading/cloning this repo, open the project's location on your computer and run "npm install" from your terminal window to install the dependencies.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
# Step 3
After installing the dependencies run the "npm run setup" command to configure the app.
type in the keys at the prompt. The script will connect to the provided space, please use a demo space as the script will DELETE all entries and content types. I repeat the script will WIPE! the space clean before importing new content.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
# Step 4
Run the app with "npm run dev".
31 changes: 31 additions & 0 deletions components/ImageComponent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import _ from "lodash";
import Image from "next/image";
const ImageComponent = (props) => {
const id = _.get(props, "id");
const image = _.get(props, "image");
const imgUrl = _.get(image, "fields.file.url");
const imgAltText = _.get(image, "fields.title");

if (!image) {
return "";
}
return (
<>
<div className="w-[400px]x overflow-hidden">
<Image
src={`https:${imgUrl}?w=1920&h=1080`}
// width={1920}
// height={1080}
width={1920}
height={1080}
layout="responsive"
alt={imgAltText}
/>
</div>

<div className="">{/* <img className="" src={imgUrl} alt={""} /> */}</div>
</>
);
};

export default ImageComponent;
66 changes: 66 additions & 0 deletions components/ProductCardComponent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { documentToReactComponents } from "@contentful/rich-text-react-renderer";
import _ from "lodash";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import richtextRenderOptions from "../lib/richtextRenderOptions";
import ImageComponent from "./ImageComponent";

const ProductCardComponent = (props) => {
const router = useRouter();
const id = _.get(props, "id");
const productIndex = _.get(props, "productIndex");
const fields = _.get(props, "fields");

const [indexIsOdd, setIndexIsOdd] = useState(false);

useEffect(() => {
if (!productIndex % 2 == 0) {
setIndexIsOdd(true);
}
return () => {};
}, []);

console.log("description field", fields.description);

if (!fields) {
return "";
}
return (
<div className="">
<div className="flex flex-col space-y-10x lg:space-y-0x lg:space-x-10x lg:flex-row w-full p-6x lg:py-10x lg:px-40x overflow-hidden rounded-md shadow-lg">
<div
className={`w-1/2 bg-blau9x bg-blau3 p-10 ${
indexIsOdd ? "order-last" : ""
}`}
>
<ImageComponent image={fields.image} />
</div>
<div className="w-1/2 bg-gelb p-10 flex flex-col items-center">
<div className=" h-1/3"></div>
<div className="flex flex-col space-y-4">
<h2 className="text-xl font-bold ">{fields.title}</h2>

<div className="">
{documentToReactComponents(
fields.description,
richtextRenderOptions
)}
</div>
<p className=" text-xl ">${fields.price}</p>
<button
onClick={() => router.push(`/products/${fields.slug}`)}
className=" bg-black text-white hover:bg-neuter rounded shadow-md"
>
BUY
</button>
</div>

<div className=" h-1/3"></div>
</div>
</div>
{/* {JSON.stringify(fields)} */}
</div>
);
};

export default ProductCardComponent;
38 changes: 38 additions & 0 deletions components/ProductSection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import _ from "lodash";
import ProductCardComponent from "./ProductCardComponent";
const ProductSection = (props) => {
const id = _.get(props, "id");
const fields = _.get(props, "fields");
const title = _.get(fields, "title");
const products = _.get(fields, "products");

if (!fields) {
return "";
}
return (
<div className="">
{/* {JSON.stringify(products)} */}
<div className="bg-red-100x flex flex-col space-y-8 p-20 border-2 rounded-md shadow-md">
<h2 className="font-bold text-2xl text-center">{title}</h2>

{Array.isArray(products)
? products.map((product, productIndex) => {
const contentType = _.get(product, "sys.contentType.sys.id");
const productId = _.get(product, "sys.id");
const fields = _.get(product, "fields");
return (
<ProductCardComponent
productIndex={productIndex}
key={productId}
id={productId}
fields={fields}
/>
);
})
: ""}
</div>
</div>
);
};

export default ProductSection;
33 changes: 33 additions & 0 deletions layouts/MainLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Head from "next/head";
import Link from "next/link";

const MainLayout = (props) => {
return (
<>
<Head>
<title>Jumpstart Shop</title>
</Head>

<div className="mt-4 p-2 bg-blau text-white">
<Link href="/">
<a>Nav</a>
</Link>
</div>

<main>
<div className="h-screenx py-20 px-60"> {props.children}</div>
</main>
<div className="mt-4 p-2 bg-blau text-white">
<a
href="https://training.contentful.com"
target="_blank"
rel="noreferrer"
>
Contentful Learning Services
</a>
</div>
</>
);
};

export default MainLayout;
64 changes: 64 additions & 0 deletions lib/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as contentful from "contentful";
import _ from "lodash";

const space_id = process.env.NEXT_PUBLIC_SPACE_ID;
const access_token = process.env.NEXT_PUBLIC_DELIVERY_TOKEN;
const preview_token = process.env.NEXT_PUBLIC_PREVIEW_TOKEN;
const environment = process.env.NEXT_PUBLIC_ENVIRONMENT;

const getOptions = (is_preview) => {
let options = {};
options.space = space_id;
options.host = is_preview ? "preview.contentful.com" : undefined;
options.accessToken = is_preview ? preview_token : access_token;
options.environment = environment ? environment : "master";
options.resolveLinks = true;

return options;
};

export const getAllLocales = async() => {
const options = getOptions(false);
const contentfulClient = contentful.createClient(options);
try {
let allLocales = await contentfulClient.getLocales();
let dataType = _.get(allLocales, "sys.type");
let items = _.get(allLocales, "items");
if (dataType === "Array") {
return items;
} else {
return false;
}
} catch (error) {
console.log("getAllLocales error ", error);
}
};

export const getEntriesByContentType = async(content_type, slug = null) => {
const options = getOptions(false);

console.log(options);

const contentfulClient = contentful.createClient(options);

if (contentfulClient) {
try {
let params = { content_type: content_type, include: 3 }; //include -> to retrieve related data(linked entries) in same request, number of levels is 3

if (slug) {
params["fields.slug"] = slug;
}

let entries = await contentfulClient.getEntries(params);

const items = _.get(entries, "items");

return { items };
} catch (error) {
console.log("getChartEntries error ->", error);
return false;
}
} else {
return false;
}
};
65 changes: 65 additions & 0 deletions lib/richtextRenderOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { BLOCKS, INLINES, MARKS } from "@contentful/rich-text-types";

const Bold = ({ children }) => (
<span className="font-bold text-blue-500"> [this is bold]{children} </span>
);
const Heading1 = ({ children }) => (
<div className="mb-4">
<span className="text-4xl md:text-6xl font-bold text-white">
{" "}
{children}{" "}
</span>{" "}
</div>
);

const Heading2 = ({ children }) => (
<div className="mb-4">
<span className="text-3xl md:text-5xl font-bold text-white">
{" "}
{children}{" "}
</span>{" "}
</div>
);
const Parag = ({ children }) => (
<div className="mb-4 ">
<p className=""> {children} </p>{" "}
</div>
);

const HyperLNK = ({ node, children }) => {
const URI = _.get(node, "data.uri");
return (
<span className="text-4xlx md:text-6xlx text-blue-200 font-bold">
{" "}
<a href={URI} target="_blank" rel="noreferrer">
{" "}
{/* {URI} */} {children}{" "}
</a>{" "}
</span>
);
};
const CustomView = () => {
return <></>;
};

const richtextRenderOptions = {
renderMark: {
[MARKS.BOLD]: (text) => <Bold> {text} </Bold>,
},
renderNode: {
[BLOCKS.HEADING_1]: (node, children) => {
return <Heading1> {children} </Heading1>;
},
[BLOCKS.HEADING_2]: (node, children) => {
return <Heading2> {children} </Heading2>;
},
[BLOCKS.PARAGRAPH]: (node, children) => {
return <Parag> {children} </Parag>;
},
[INLINES.HYPERLINK]: (node, children) => {
return <HyperLNK node={node}> {children} </HyperLNK>;
},
},
};

export default richtextRenderOptions;
7 changes: 5 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module.exports = {
reactStrictMode: true,
}
reactStrictMode: true,
images: {
domains: ["images.ctfassets.net"],
},
};
Loading

0 comments on commit f90aa69

Please sign in to comment.