import React , { useState , useEffect , useContext } from "react" ; import { NextPage } from "next" ; import Head from "next/head" ; import { useQuery , useMutation } from "@apollo/react-hooks" ; import Cookies from "js-cookie" ; import { useCheckoutEffect , createCheckout , checkoutQuery , checkoutLineItemsAdd , checkoutLineItemsUpdate , checkoutLineItemsRemove , checkoutCustomerAssociate , getCheckout } from "../../services/checkout" ; import Layout from "../../components/Layout/Layout" ; import CartContext from "../../components/Cart/CartContext" ; import { get } from "../../services/product" ; import { getProductsInfo } from "../../services/products" ; interface Props { shopLoading : any ; shopError : any ; product : any ; } const ProductPage = ( { shopLoading , shopError , product } ) => { const { isCartOpen , setIsCartOpen , checkout , setCheckout } = useContext ( CartContext ) ; const [ variantQuantity , setVariantQuantity ] = useState ( 1 ) ; const checkoutId = Cookies . get ( "checkoutId" ) ; const handleQuantityChange = event => { setVariantQuantity ( event . target . value ) ; } ; const [ lineItemAddMutation , { data : lineItemAddData , loading : lineItemAddLoading , error : lineItemAddError } ] = useMutation ( checkoutLineItemsAdd ) ; useCheckoutEffect ( lineItemAddData , "checkoutLineItemsAdd" , setCheckout ) ; const addVariantToCart = async ( variantId , quantity ) => { const variables = { checkoutId : checkoutId , lineItems : [ { variantId , quantity : parseInt ( quantity , 10 ) } ] } ; lineItemAddMutation ( { variables } ) . then ( res => { setIsCartOpen ( true ) ; } ) ; } ; if ( shopLoading ) { return < p > Loading ... < /p>; } if ( shopError ) { return < p > { shopError . message } < /p>; } const variants = product . variants . edges . map ( ( { node } ) => ( { ... node } ) ) ; const variant = product . variants . edges [ 0 ] . node ; const images = product . images . edges ; const imageSrc = images . length ? images [ 0 ] . node . transformedSrc : "http://www.netum.vn/public/default/img/icon/default-product-image.png" ; const price = product . priceRange . minVariantPrice . amount ; const altText = images . length ? images [ 0 ] . node . altText : "" ; return ( < > < Head > < title > { product . title } - Next Shopify Storefront < /title> < /Head> < Layout > < section className = "text-gray-700 body-font overflow-hidden" > < div className = "container px-5 py-24 mx-auto" > < div className = "lg:w-4/5 mx-auto flex flex-wrap" > < img alt = "ecommerce" className = "lg:w-1/2 w-full lg:h-auto h-64 object-cover object-center rounded" src = { imageSrc } / > < div className = "lg:w-1/2 w-full lg:pl-10 lg:py-6 mt-6 lg:mt-0" > < h2 className = "text-sm title-font border-0 mb-0 text-gray-500 tracking-widest" > BRAND NAME < /h2> < h1 className = "text-gray-900 mt-0 text-3xl title-font font-medium mb-1" > { product . title } < /h1> < div className = "flex mb-4" > < span className = "flex items-center" > < svg fill = "currentColor" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4 text-blue-500" viewBox = "0 0 24 24" > < path d = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" / > < /svg> < svg fill = "currentColor" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4 text-blue-500" viewBox = "0 0 24 24" > < path d = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" / > < /svg> < svg fill = "currentColor" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4 text-blue-500" viewBox = "0 0 24 24" > < path d = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" / > < /svg> < svg fill = "currentColor" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4 text-blue-500" viewBox = "0 0 24 24" > < path d = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" / > < /svg> < svg fill = "none" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4 text-blue-500" viewBox = "0 0 24 24" > < path d = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" / > < /svg> < span className = "text-gray-600 ml-3" > 4 Reviews < /span> < /span> < span className = "flex ml-3 pl-3 py-2 border-l-2 border-gray-200" > < a className = "text-gray-500" > < svg fill = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-5 h-5" viewBox = "0 0 24 24" > < path d = "M18 2h-3a5 5 0 00-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 011-1h3z" / > < /svg> < /a> < a className = "ml-2 text-gray-500" > < svg fill = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-5 h-5" viewBox = "0 0 24 24" > < path d = "M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z" / > < /svg> < /a> < a className = "ml-2 text-gray-500" > < svg fill = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-5 h-5" viewBox = "0 0 24 24" > < path d = "M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z" / > < /svg> < /a> < /span> < /div> < p className = "leading-relaxed" > { product . description } < /p> < div className = "flex mt-6 items-center pb-5 border-b-2 border-gray-200 mb-5" > < div className = "flex" > < span className = "mr-3" > Color < /span> < button className = "border-2 border-gray-300 rounded-full w-6 h-6 focus:outline-none" / > < button className = "border-2 border-gray-300 ml-1 bg-gray-700 rounded-full w-6 h-6 focus:outline-none" / > < button className = "border-2 border-gray-300 ml-1 bg-blue-500 rounded-full w-6 h-6 focus:outline-none" / > < /div> < div className = "flex ml-6 items-center" > < span className = "mr-3" > Size < /span> < div className = "relative" > < select className = "rounded border appearance-none border-gray-400 py-2 focus:outline-none focus:border-blue-500 text-base pl-3 pr-10" > < option > S < /option> < option > M < /option> < option > L < /option> < option > XL < /option> < /select> < span className = "absolute right-0 top-0 h-full w-10 text-center text-gray-600 pointer-events-none flex items-center justify-center" > < svg fill = "none" stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-4 h-4" viewBox = "0 0 24 24" > < path d = "M6 9l6 6 6-6" / > < /svg> < /span> < /div> < /div> < /div> < label className = "Product__option" > Qty : { " " } < input className = "mb-4 border-2 rounded w-10 text-center" min = "1" type = "number" defaultValue = { variantQuantity } onChange = { handleQuantityChange } > < /input> < /label> < div className = "flex" > < span className = "title-font font-medium text-2xl text-gray-900" > $ { parseFloat ( price ) . toFixed ( 2 ) } < /span> < button className = "flex ml-auto text-white bg-blue-500 border-0 py-2 px-6 focus:outline-none hover:bg-blue-600 rounded" onClick = { ( ) => addVariantToCart ( variant . id , variantQuantity ) } > Add to cart < /button> < button className = "rounded-full w-10 h-10 bg-gray-200 p-0 border-0 inline-flex items-center justify-center text-gray-500 ml-4" > < svg fill = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } className = "w-5 h-5" viewBox = "0 0 24 24" > < path d = "M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z" / > < /svg> < /button> < /div> < /div> < /div> < /div> < /section> < /Layout> < />); } ; export async function getStaticProps ( { ... ctx } ) { const { producthandle } = ctx . params ; const product = await get ( { handle : producthandle } ) ; return { props : { product : product . productByHandle } } ; } export async function getStaticPaths ( ) { const products = await getProductsInfo ( ) ; return { paths : products . map ( ( { node } ) => "/products/" + node . handle ) , fallback : false } ; } export default ProductPage ;