/** @jsx jsx */ import { useState, useEffect, useMemo } from "react" import { Styled, jsx } from "theme-ui" import Img from "gatsby-image" import { Grid, Button, Alert, Close } from "@theme-ui/components" import { Layout, SEO } from "../components" import { Thumbnail, OptionPicker } from "./components" import { graphql } from "gatsby" import { prepareVariantsWithOptions, prepareVariantsImages } from "./utilities" import { useAddItemToCart } from "../context/StoreContext" const ProductPage = ({ data: { shopifyProduct: product } }) => { const colors = product.options.find( option => option.name.toLowerCase() === "color" ).values const sizes = product.options.find( option => option.name.toLowerCase() === "size" ).values const variants = useMemo(() => prepareVariantsWithOptions(product.variants), [ product.variants, ]) const images = useMemo(() => prepareVariantsImages(variants, "color"), [ variants, ]) if (images.length < 1) { throw new Error("Must have at least one product image!") } const addItemToCart = useAddItemToCart() const [variant, setVariant] = useState(variants[0]) const [color, setColor] = useState(variant.color) const [size, setSize] = useState(variant.size) const [addedToCartMessage, setAddedToCartMessage] = useState(null) useEffect(() => { const newVariant = variants.find(variant => { return variant.size === size && variant.color === color }) if (variant.shopifyId !== newVariant.shopifyId) { setVariant(newVariant) } }, [size, color, variants, variant.shopifyId]) const gallery = images.length > 1 ? ( <Grid gap={2} columns={6}> {images.map(({ src, color }) => ( <Thumbnail key={color} src={src} onClick={() => setColor(color)} /> ))} </Grid> ) : null function handleAddToCart() { addItemToCart(variant.shopifyId, 1) setAddedToCartMessage("🛒 Added to your cart!") } return ( <Layout> <SEO title={product.title} /> {addedToCartMessage ? ( <Alert sx={{ mb: 4 }} variant="primary"> {addedToCartMessage} <Close ml="auto" mr={-2} sx={{ "&:hover": { cursor: "pointer", }, }} onClick={() => setAddedToCartMessage(null)} /> </Alert> ) : null} <Grid gap={4} columns={2}> <div> <div sx={{ border: "1px solid gray", padding: 2, marginBottom: 2, }} > <Img fluid={variant.image.localFile.childImageSharp.fluid} /> </div> {gallery} </div> <div sx={{ display: "flex", flexDirection: "column" }}> <Styled.h1 sx={{ mt: 0, mb: 2 }}>{product.title}</Styled.h1> <div dangerouslySetInnerHTML={{ __html: product.descriptionHtml }} /> <div> <Grid padding={2} columns={2}> <OptionPicker key="Color" name="Color" options={colors} selected={color} onChange={event => setColor(event.target.value)} /> <OptionPicker key="Size" name="Size" options={sizes} selected={size} onChange={event => setSize(event.target.value)} /> </Grid> </div> <Button sx={{ margin: 2, display: "block" }} onClick={handleAddToCart} > Add to Cart </Button> </div> </Grid> </Layout> ) } export default ProductPage export const ProductPageQuery = graphql` query productPage($productId: String!) { shopifyProduct(id: { eq: $productId }) { id title descriptionHtml options { name values } variants { shopifyId selectedOptions { name value } image { localFile { childImageSharp { fluid(maxWidth: 446) { ...GatsbyImageSharpFluid_withWebp } } } } } } } `