From a8543d11df2d47edd6dd5fd21b1a26ee16a8b26d Mon Sep 17 00:00:00 2001 From: Ashelyn Dawn Date: Wed, 1 Apr 2020 20:05:43 -0600 Subject: [PATCH] Cart protections --- components/card/card.js | 22 +++++++++++++++++++--- components/card/style.module.css | 5 +++-- components/header/header.js | 4 +++- db/sql/2-views.sql | 4 ++-- hooks/useCart.js | 6 ++++++ pages/_app.js | 11 ++++++----- pages/store/cart.js | 15 ++++++++++++--- pages/store/item/[slug].js | 11 +++++++++-- 8 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 hooks/useCart.js 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 (

{item.name}

@@ -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 ( - <> -
    -
    + +
    +