You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.9 KiB
JavaScript

import React, {useState} from 'react'
import Head from 'next/head'
import Router from 'next/router'
import {FormController, IntegerInput, Button} from '~/components/form'
import isNum from 'validator/lib/isNumeric'
import useCart, {useSetCart} from '~/hooks/useCart'
import styles from './style.module.css'
Item.getInitialProps = async function({ctx: {axios, query: {slug}}}){
const {data: item} = await axios.get(`/api/items/by-slug/${slug}`)
if(!item) {
const err = new Error("Not found")
err.status = 404
throw err;
}
return {item}
}
// TODO: Modal with full image size on clicking preview
export default function Item({item}){
const cart = useCart()
const setCart = useSetCart()
// Pick first one with featured flag or 0
const featuredIndex = item.images.reduce((p, im, i) => ((p !== undefined) ? p : (im.featured ? i : undefined)), undefined) || 0
const [selectedIndex, setSelected] = useState(featuredIndex);
const numInCart = cart?.items?.find(i => i.item.uuid === item.uuid)?.count || 0
return (
<>
<Head>
<title>{item.name} | Society of Socks</title>
</Head>
<div className={styles.pageContainer}>
<div className={'dark ' + styles.itemDetails}>
{item.images && item.images.length > 0 && (
<div className={styles.imageContainer}>
<div className={styles.card}>
<picture>
<source srcset={`/api/images/${item.images[selectedIndex].uuid}/thumb.webp`} type="image/webp"/>
<img src={`/api/images/${item.images[selectedIndex].uuid}/thumb.png`} />
</picture>
</div>
{item.images && item.images.length > 1 &&
<div className={styles.imageSelector}>
{item.images.map((image, index) => (
<picture>
<source srcset={`/api/images/${image.uuid}/thumb.webp`} type="image/webp"/>
<img key={image.uuid}
onClick={()=>setSelected(index)}
className={index === selectedIndex ? styles.selectedImage : undefined}
src={`/api/images/${image.uuid}/thumb.png`}
/>
</picture>
))}
</div>
}
</div>
)}
<div className={styles.controls}>
<h2>{item.name}</h2>
{ item.description.split('\n').map(p=>p.trim()).filter(p=>p !== '').map((p,i)=><p key={i}>{p}</p>) }
<FormController className={styles.form} url={`/api/cart/add/${item.uuid}`} afterSubmit={(cart)=>{setCart(cart); Router.push('/store/cart')}}>
<IntegerInput label="Add to cart" name="count" initialValue="1" minimum="1" validate={value=>isNum(value, {no_symbols: true})} />
{
item.number_in_stock > 0
? <Button type="submit">Add to cart</Button>
: <Button enabled={false} type="submit">Out of stock</Button>
}
</FormController>
<div className={styles.notes}>
<span>Price: ${(parseInt(item.price_cents) / 100).toFixed(2)} each</span>
<span>
{
item.number_in_stock
? item.number_in_stock + ' in stock'
: 'Out of stock'
}
</span>
<span>{numInCart} in cart</span>
</div>
</div>
</div>
<div className={styles.moreDetails}>
<h2>Additional Information</h2>
<p>All socks are only available in adult medium sizes (approximately US Men's size 10 - 13 depending on stretching) at the moment - we're working on getting more sizes available but not quite ready for that yet.</p>
<p>All purchases are shipped within a few days of your purchase, (USPS first class).</p>
</div>
</div>
</>
)
}