diff --git a/components/card/card.js b/components/card/card.js
index db40cd3..a3c9d2c 100644
--- a/components/card/card.js
+++ b/components/card/card.js
@@ -1,12 +1,23 @@
import React from 'react'
import Link from 'next/link'
+import useCart from '../../hooks/useCart'
import styles from './style.module.css'
+import axios from 'axios'
-export default function Card({item, numberInCart}) {
+export default function Card({item}) {
+ const [cart, setCart] = useCart()
+ const numInCart = cart?.items?.find(i => i.item.uuid === item.uuid)?.count || 0
let featuredImage = item.images.filter(i=>i.featured)[0]
if(!featuredImage) featuredImage = item.images[0]
+ const addToCart = async ev => {
+ if(ev) ev.preventDefault()
+
+ const {data: newCart} = await axios.post(`/api/cart/add/${item.uuid}`, {count: 1})
+ setCart(newCart)
+ }
+
return (
@@ -24,14 +35,19 @@ export default function Card({item, numberInCart}) {
: 'Currently out of stock'
}
-
Details
+
Details
{
item.number_in_stock > 0 && (
- 0)}>Add to Cart
+
)
}
+ {numInCart > 0 && (
+
+ ({numInCart} in cart)
+
+ )}
)
diff --git a/components/card/style.module.css b/components/card/style.module.css
index b005e4e..aafec8f 100644
--- a/components/card/style.module.css
+++ b/components/card/style.module.css
@@ -38,7 +38,7 @@
border-bottom:solid 1px black;
}
-.card a:hover{
+.card a:hover, .card button:global(.buttonLink):hover{
color: #760c88;
border-color: #760c88;
transition: .2s ease-in-out;
@@ -80,7 +80,8 @@
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
-.card p, .card a{
+.card p, .card a, .card button:global(.buttonLink){
+ font-family: inherit;
color:black;
opacity:.87;
}
diff --git a/components/header/header.js b/components/header/header.js
index c2050c5..b3d924d 100644
--- a/components/header/header.js
+++ b/components/header/header.js
@@ -2,10 +2,12 @@ import Link from "next/link"
import PropTypes from "prop-types"
import React from "react"
+import useCart from '../../hooks/useCart'
import logo from './sos-logo.png'
import styles from './style.module.css'
-const Header = ({user, cart}) => {
+const Header = ({user}) => {
+ const [cart] = useCart()
const cartSize = (cart && cart.items.length) ? cart.items.map(item => item.count).reduce((sum, current) => (sum + current)) : 0
return (
diff --git a/db/sql/2-views.sql b/db/sql/2-views.sql
index eacf0fd..a1d37e5 100644
--- a/db/sql/2-views.sql
+++ b/db/sql/2-views.sql
@@ -14,8 +14,8 @@ create or replace view sos.v_item as
(
select
stockchange_item_uuid,
- sum(case when stockchange_direction = 'added' then stockchange_change end)::int4 as num_added,
- sum(case when stockchange_direction = 'subtracted' then stockchange_change end)::int4 as num_removed
+ coalesce(sum(case when stockchange_direction = 'added' then stockchange_change end)::int4, 0) as num_added,
+ coalesce(sum(case when stockchange_direction = 'subtracted' then stockchange_change end)::int4, 0) as num_removed
from sos."item_stockchange"
group by stockchange_item_uuid
) stock_counts
diff --git a/hooks/useCart.js b/hooks/useCart.js
new file mode 100644
index 0000000..12b43f6
--- /dev/null
+++ b/hooks/useCart.js
@@ -0,0 +1,6 @@
+import React, {useContext} from 'react'
+
+const CartContext = React.createContext(null);
+
+export const CartContextProvider = CartContext.Provider;
+export default () => useContext(CartContext)
diff --git a/pages/_app.js b/pages/_app.js
index b1ade88..bb067bb 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -2,6 +2,7 @@ import React, {useState} from "react"
import PropTypes from "prop-types"
import axios from 'axios'
+import {CartContextProvider} from '../hooks/useCart'
import Header from '~/components/header'
import Footer from '~/components/footer'
import "../styles/layout.css"
@@ -30,14 +31,14 @@ Layout.getInitialProps = async ({Component, ctx}) => {
}
function Layout({ Component, pageProps, user, cart: _cart }){
- const [cart, setCart] = useState(_cart)
+ const cartState = useState(_cart)
return (
- <>
-
-
+
+
+
- >
+
)
}
diff --git a/pages/store/cart.js b/pages/store/cart.js
index 6ffcbba..fa8fa66 100644
--- a/pages/store/cart.js
+++ b/pages/store/cart.js
@@ -1,12 +1,16 @@
import React from 'react'
+import Link from 'next/link'
import axios from 'axios'
import Head from 'next/head'
+import useCart from '../../hooks/useCart'
import {FormController, Input, Button} from '~/components/form'
import Table from '~/components/table'
-export default function Cart({cart, setCart}){
+export default function Cart(){
+ const [cart, setCart] = useCart()
const numItems = (cart?.items) ? cart.items.length : 0
+ const allInStock = !cart?.items.some(item => !item.number_in_stock || item.number_in_stock < 1)
const handleRemove = id => async ev => {
if(ev) ev.preventDefault()
@@ -28,7 +32,12 @@ export default function Cart({cart, setCart}){
numItems > 0
? row.item.name},
+ {name: 'Item', extractor: row => (
+ <>
+ {row.item.name}
+ {(!row.item.number_in_stock || row.item.number_in_stock < 1) && Out of stock}
+ >
+ )},
{name: 'Quantity in Cart', extractor: row => row.count},
{name: 'Price Each', extractor: row => '$' + (row.item.price_cents / 100).toFixed(2)},
{name: 'Total Price', extractor: row => '$' + (row.count * row.item.price_cents / 100).toFixed(2)},
@@ -63,7 +72,7 @@ export default function Cart({cart, setCart}){
}
-
+
>
)
diff --git a/pages/store/item/[slug].js b/pages/store/item/[slug].js
index 8044746..96c837e 100644
--- a/pages/store/item/[slug].js
+++ b/pages/store/item/[slug].js
@@ -4,6 +4,7 @@ import Router from 'next/router'
import {FormController, NumInput, Button} from '~/components/form'
import isNum from 'validator/lib/isNumeric'
+import useCart from '../../../hooks/useCart'
import styles from './style.module.css'
Item.getInitialProps = async function({ctx: {axios, query: {slug}}}){
@@ -19,7 +20,8 @@ Item.getInitialProps = async function({ctx: {axios, query: {slug}}}){
}
// TODO: Modal with full image size on clicking preview
-export default function Item({item, cart, setCart}){
+export default function Item({item}){
+ const [cart, setCart] = useCart()
// 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);
@@ -55,7 +57,12 @@ export default function Item({item, cart, setCart}){
{setCart(cart); Router.push('/store/cart')}}>
isNum(value, {no_symbols: true})} />
-
+ {
+ item.number_in_stock > 0
+ ?
+ :
+ }
+