diff --git a/gatsby-browser.js b/gatsby-browser.js index 3ace87e..0eecdb3 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -1 +1,7 @@ +import React from "react"; import "./src/styles/scss/index.scss"; + +import { UserProvider } from "./src/context/UserContext"; +export const wrapRootElement = ({ element }) => ( + {element} +); diff --git a/gatsby-node.js b/gatsby-node.js index 6ab6215..0d581bf 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -3,7 +3,7 @@ const path = require("path"); exports.createPages = async ({ graphql, actions, reporter }) => { const { createPage } = actions; - const ProductPage = path.resolve("./src/pages/book/_slug.tsx"); + const ProductPage = path.resolve("./src/components/Product.tsx"); const result = await graphql( ` diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 1333d7e..fdde46a 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,23 +1,27 @@ -import React, { useState } from "react"; +import React, { useContext, useState } from "react"; import { Link, navigate } from "gatsby"; +import UserContext from "../context/UserContext"; type NavbarProps = { showBackButton?: boolean; }; const Navbar = ({ showBackButton }: NavbarProps) => { - const [token] = useState(""); + const { user, setUser } = useContext(UserContext); + const [loading, setLoading] = useState(false); const handleSignOut = async (event: any) => { event.preventDefault(); + setLoading(true); try { - await fetch(`/api/logout?token=${token}`, { + await fetch(`/api/logout?token=${user}`, { method: "POST", }).catch((err) => { console.error(`Logout error: ${err}`); }); } finally { - window.localStorage.removeItem("google:tokens"); + setLoading(false); + setUser(""); navigate("/"); } }; @@ -37,13 +41,13 @@ const Navbar = ({ showBackButton }: NavbarProps) => {
  • - {!!token && ( + {!!user && ( )}
  • diff --git a/src/components/PrivateRoute.tsx b/src/components/PrivateRoute.tsx new file mode 100644 index 0000000..a2730d3 --- /dev/null +++ b/src/components/PrivateRoute.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import Layout from "../components/templates/Layout"; +import { navigate } from "gatsby"; +import UserContext from "../context/UserContext"; +import { useContext } from "react"; + +const PrivateRoute = ({ component: Component, ...rest }: any) => { + const { user } = useContext(UserContext); + + if (!user) { + navigate(`/`); + return null; + } + + return ( + + + + ); +}; + +export default PrivateRoute; diff --git a/src/pages/book/_slug.module.css b/src/components/Product.module.css similarity index 100% rename from src/pages/book/_slug.module.css rename to src/components/Product.module.css diff --git a/src/pages/book/_slug.tsx b/src/components/Product.tsx similarity index 85% rename from src/pages/book/_slug.tsx rename to src/components/Product.tsx index a2fb85f..566bb5d 100644 --- a/src/pages/book/_slug.tsx +++ b/src/components/Product.tsx @@ -1,31 +1,45 @@ -import React, { ReactPropTypes } from "react"; +import React, { ReactPropTypes, useState } from "react"; import { graphql, navigate } from "gatsby"; import { get } from "lodash"; import { renderRichText } from "gatsby-source-contentful/rich-text"; import { PaystackConsumer } from "react-paystack"; -import Layout from "../../components/templates/Layout"; -import StarRating from "../../components/StarRating"; +import StarRating from "./StarRating"; -import * as styles from "./_slug.module.css"; +import * as styles from "./Product.module.css"; +import Layout from "./templates/Layout"; + +const generateReference = (): string => { + let text = ""; + let possible = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for (let i = 0; i < 10; i++) + text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; +}; const payStackConfig = { - reference: new Date().getTime().toString(), - email: process.env.GATSBY_PAYSTACK_TEST_EMAIL || "", - publicKey: process.env.GATSBY_PAYSTACK_PUBLIC_KEY || "", + email: process.env.GATSBY_PAYSTACK_TEST_EMAIL, + publicKey: process.env.GATSBY_PAYSTACK_PUBLIC_KEY, }; const ProductPage = (props: ReactPropTypes) => { const product = get(props, `data.contentfulProduct`); + const [reference, setReference] = useState(generateReference()); const handleSuccess = (_reference: string) => { // TODO: send reference navigate("/book/appointment"); }; - const handleClose = () => {}; + const handleClose = (): void => { + setReference(generateReference()); + }; const componentProps = { + reference, ...payStackConfig, amount: product.price * 500 * 100, text: "Book Sleep Appointment", diff --git a/src/components/Products.tsx b/src/components/Products.tsx new file mode 100644 index 0000000..09eff37 --- /dev/null +++ b/src/components/Products.tsx @@ -0,0 +1,64 @@ +import React from "react"; +import { graphql, Link, useStaticQuery } from "gatsby"; +import { ProductType } from "../types"; +import StarRating from "./StarRating"; + +const ProductListPage = () => { + const productsList = useStaticQuery(graphql` + query { + allContentfulProduct { + nodes { + contentful_id + name + image { + file { + fileName + url + } + } + starrating + reviews + price + } + } + } + `); + + return ( +
    +

    + Pick your favorite mattress +

    + +
    + {productsList.allContentfulProduct.nodes.map((product: ProductType) => ( +
    +
    +
    + +
    +
    + +

    + {product.name} +

    + +

    + ${product.price} + + +

    +
    +
    +
    + ))} +
    +
    + ); +}; + +export default ProductListPage; diff --git a/src/components/StarRating.tsx b/src/components/StarRating.tsx index fc12341..42ed166 100644 --- a/src/components/StarRating.tsx +++ b/src/components/StarRating.tsx @@ -11,20 +11,18 @@ const StarRating = ({ stars, className }: StarRatingProp) => { {[...Array(5)].map((_, index) => { index += 1; return ( - <> - - + ); })} diff --git a/src/components/templates/Layout/index.tsx b/src/components/templates/Layout/index.tsx index e470936..335c001 100644 --- a/src/components/templates/Layout/index.tsx +++ b/src/components/templates/Layout/index.tsx @@ -2,7 +2,6 @@ import React from "react"; import { Helmet } from "react-helmet"; import Navbar from "../../Navbar"; import Footer from "../../Footer"; -import UserProvider from "../../../context/UserContext"; interface LayoutInterface { children: React.ReactNode; @@ -11,7 +10,7 @@ interface LayoutInterface { } const Layout = ({ children, showBackButton }: LayoutInterface) => ( - + <> More sleep @@ -19,7 +18,7 @@ const Layout = ({ children, showBackButton }: LayoutInterface) => ( {children}