diff --git a/src/App.js b/src/App.js index 1aa8b96..65078a5 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import styled from "styled-components"; import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom"; import { Overview } from "./Overview"; -import { Checkout } from "./Checkout/Checkout"; +import { CheckOut } from "./CheckOut/CheckOut"; import { Details } from "./Details"; import { OrderCompleted } from "./OrderCompleted/OrderCompleted"; import { ShoppingCart } from "./ShoppingCart/ShoppingCart"; @@ -11,7 +11,6 @@ const Title = styled.h1` font-size: 1.5em; text-align: center; color: palevioletred; - border-bottom: 1px solid #d0d1d3; `; const NavBar = styled.nav` @@ -82,11 +81,14 @@ const App = () => {
  • Order Completed
  • +
  • + Shopping Cart +
  • - Pokemon ecommerce + Pokemon E-Commerce @@ -99,7 +101,7 @@ const App = () => { - + diff --git a/src/Checkout/Checkout.js b/src/Checkout/Checkout.js index baceed3..f4c1770 100644 --- a/src/Checkout/Checkout.js +++ b/src/Checkout/Checkout.js @@ -1,3 +1,247 @@ -export function Checkout() { - return
    Checkout
    ; +import { useState } from "react"; +import { useHistory } from "react-router-dom"; +import styled from "styled-components"; +import { addOrderDetails } from "../common/pokemonStorage"; + +const SubmitButton = styled.button` + grid-column-start: first; + grid-column-end: second; + grid-row-start: r6; + grid-row-end: r6; + font-family: inherit; + font-size: 100%; + line-height: 1.15; + font-weight: 700; + margin: 14px 14px 14px 14px; + background-color: black; + color: white; + outline: none; + display: inline-flex; + justify-content: center; + border: 0; + cursor: pointer; + padding: 24px 0; + + align-self: end; + &:hover { + opacity: 0.8; + } +`; +const LayoutStyle = styled.div` + display: grid; + grid-template-columns: [first] 50% [second] 50%; + grid-template-rows: [r1] 65px [r2] 65px [r3] 65px [r4] 65px [r5] 65px [r6] 80px; + max-width: 800px; + margin: auto; +`; + +const PanelStyle1 = styled.div` + grid-column-start: first; + grid-column-end: second; + grid-row-start: r1; + grid-row-end: r1; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const PanelStyle2 = styled.div` + grid-column-start: first; + grid-column-end: first; + grid-row-start: r2; + grid-row-end: r2; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const PanelStyle3 = styled.div` + grid-column-start: second; + grid-column-end: second; + grid-row-start: r2; + grid-row-end: r2; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const PanelStyle4 = styled.div` + grid-column-start: first; + grid-column-end: second; + grid-row-start: r3; + grid-row-end: r3; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const PanelStyle5 = styled.div` + grid-column-start: first; + grid-column-end: second; + grid-row-start: r4; + grid-row-end: r4; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const PanelStyle6 = styled.div` + grid-column-start: first; + grid-column-end: second; + grid-row-start: r5; + grid-row-end: r5; + margin-right: 12px; + margin-left: 12px; + margin-top: 0; + margin-bottom: 0; + background-color: white; +`; + +const Input = styled.input` + width: 100%; + font-family: "Source Sans Pro", sans-serif; + padding: 8px 8px; + margin: 5px auto 5px auto; + display: block; + text-align: center; + font-size: 18px; + color: black; + font-weight: 300; +`; + +export function CheckOut() { + const [contact, setContact] = useState({ + fName: "", + lName: "", + email: "", + address: "", + creditcard: "", + }); + const history = useHistory(); + const handleSubmit = () => { + addOrderDetails({ + fName: contact.fName, + lName: contact.lName, + email: contact.email, + address: contact.address, + creditcard: contact.creditcard, + }); + history.push(`/order-completed`); + }; + + function handleChange(event) { + const { name, value } = event.target; + + setContact((prevValue) => { + if (name === "fName") { + return { + fName: value, + lName: prevValue.lName, + email: prevValue.email, + address: prevValue.address, + creditcard: prevValue.creditcard, + }; + } + if (name === "lName") { + return { + fName: prevValue.fName, + lName: value, + email: prevValue.email, + address: prevValue.address, + creditcard: prevValue.creditcard, + }; + } + if (name === "email") { + return { + fName: prevValue.fName, + lName: prevValue.lName, + email: value, + address: prevValue.address, + creditcard: prevValue.creditcard, + }; + } + if (name === "address") { + return { + fName: prevValue.fName, + lName: prevValue.lName, + email: prevValue.email, + address: value, + creditcard: prevValue.creditcard, + }; + } + if (name === "creditcard") { + return { + fName: prevValue.fName, + lName: prevValue.lName, + email: prevValue.email, + address: prevValue.address, + creditcard: value, + }; + } + return ""; + }); + } + + return ( + + +

    + Hello {contact.fName} {contact.lName} +

    +

    {contact.email}

    +
    + + + + + + + + + + + + + + + + + Submit +
    + ); } diff --git a/src/OrderCompleted/OrderCompleted.js b/src/OrderCompleted/OrderCompleted.js index ecb8cf3..d90d48f 100644 --- a/src/OrderCompleted/OrderCompleted.js +++ b/src/OrderCompleted/OrderCompleted.js @@ -1,3 +1,60 @@ +import styled from "styled-components"; +import { GRAY } from "./constants"; +import { Card } from "./components/Card"; +import { Total } from "./components/Total"; +import { + getCartItems, + getOrderDetails, + getCounter, +} from "../common/pokemonStorage"; + +const LayoutStyle = styled.div` + display: grid; + grid-template-columns: 2fr 1fr; + max-width: 1024px; + background-color: ${GRAY}; + margin: auto; +`; + +const PanelStyle = styled.div` + margin: 1rem; + background-color: white; + padding: 1rem; +`; + +const ScrollStyle = styled.div` + overflow-y: scroll; + max-height: 500px; +`; + export function OrderCompleted() { - return
    OrderCompleted
    ; + const cart = getCartItems(); + const order = getOrderDetails(); + console.log("order", order); + const cartCounter = getCounter(); + const total = cart.reduce( + (acc, current) => acc + current.price * current.quantity, + 0 + ); + + return ( +
    +

    + {order.fName} {order.lName} +

    + + +

    Order Details: (Total {cartCounter} articles)

    + + {cart.map((item) => ( + + ))} + +
    + + + +
    +
    + ); } diff --git a/src/OrderCompleted/components/Card.js b/src/OrderCompleted/components/Card.js new file mode 100644 index 0000000..9c33ef1 --- /dev/null +++ b/src/OrderCompleted/components/Card.js @@ -0,0 +1,40 @@ +import styled from "styled-components"; +import { GRAY } from "../constants"; +import { HRStyle } from "./Hr"; + +const CardStyle = styled.div` + display: grid; + grid-template-columns: 1fr 3fr 1fr; + img { + width: 100px; + background-color: ${GRAY}; + } + div { + padding: 1rem; + } +`; + +const CardPriceStyle = styled.div` + padding: 1rem; + display: flex; + flex-direction: column; + align-items: flex-end; +`; + + + +export const Card = ({ name, img, price, quantity }) => ( + <> + + {name} +
    + {name} +
    + +

    {quantity}

    +

    {price * quantity}

    +
    +
    + + +); diff --git a/src/OrderCompleted/components/Hr.js b/src/OrderCompleted/components/Hr.js new file mode 100644 index 0000000..cfb9b66 --- /dev/null +++ b/src/OrderCompleted/components/Hr.js @@ -0,0 +1,6 @@ +import styled from "styled-components"; +import { GRAY } from "../constants"; + +export const HRStyle = styled.hr` + border: 0.5px solid ${GRAY}; +`; diff --git a/src/OrderCompleted/components/Total.js b/src/OrderCompleted/components/Total.js new file mode 100644 index 0000000..1870991 --- /dev/null +++ b/src/OrderCompleted/components/Total.js @@ -0,0 +1,57 @@ +import { useHistory } from "react-router-dom"; +import styled from "styled-components"; +import { HRStyle } from "./Hr"; +import {} from "module"; +import { emptyStorage } from "../../common/pokemonStorage"; + +const TotalItemStyle = styled.div` + display: flex; + justify-content: space-between; +`; + +const CheckoutButton = styled.button` + font-family: inherit; + font-size: 100%; + line-height: 1.15; + font-weight: 700; + margin: 24px 0 32px 0; + width: 100%; + background-color: black; + color: white; + outline: none; + display: inline-flex; + justify-content: center; + border: 0; + cursor: pointer; + padding: 24px 0; + + align-self: end; + &:hover { + opacity: 0.8; + } +`; + +export const Total = ({ total }) => { + const history = useHistory(); + + const redirect = () => { + emptyStorage(); + history.push(`/`); + }; + return ( +
    +

    Total

    + + Subtotal + {(total * 0.8).toFixed(2)} + + + + Total (VAT included) + {total} + + + Thank You +
    + ); +}; diff --git a/src/OrderCompleted/constants.js b/src/OrderCompleted/constants.js new file mode 100644 index 0000000..e412307 --- /dev/null +++ b/src/OrderCompleted/constants.js @@ -0,0 +1 @@ +export const GRAY = `#efeff0`; diff --git a/src/ShoppingCart/ShoppingCart.js b/src/ShoppingCart/ShoppingCart.js index 1f1a7f8..2b0b87c 100644 --- a/src/ShoppingCart/ShoppingCart.js +++ b/src/ShoppingCart/ShoppingCart.js @@ -3,7 +3,12 @@ import { useState } from "react"; import { GRAY } from "./constants"; import { Card } from "./components/Card"; import { Total } from "./components/Total"; -import { getCartItems, removeFromCart } from "../common/pokemonStorage"; +import { + getCartItems, + removeFromCart, + addToCart, + getCounter, +} from "../common/pokemonStorage"; const LayoutStyle = styled.div` display: grid; @@ -26,9 +31,26 @@ const ScrollStyle = styled.div` export function ShoppingCart() { const [cart, setCart] = useState(getCartItems()); + const [cartCounter, setCartCounter] = useState(getCounter()); + const [total, setTotal] = useState( + cart.reduce((acc, current) => acc + current.price * current.quantity, 0) + ); + + const setCartTotal = () => { + setTotal( + cart.reduce((acc, current) => acc + current.price * current.quantity, 0) + ); + }; const handleRemove = (name) => { setCart(removeFromCart(name)); + setCartCounter(getCounter()); + setCartTotal(); + }; + const handleAdd = (item) => { + setCart(addToCart(item)); + setCartCounter(getCounter()); + setCartTotal(); }; if (cart.length === 0) { return ( @@ -43,19 +65,20 @@ export function ShoppingCart() { return ( -

    Place you order ({cart.length} article)

    +

    Place you order ({cartCounter} article)

    {cart.map((item) => ( handleAdd(item)} onRemove={() => handleRemove(item.name)} /> ))}
    - acc + current.price, 0)} /> +
    ); diff --git a/src/ShoppingCart/components/Card.js b/src/ShoppingCart/components/Card.js index 3c476fd..e3702af 100644 --- a/src/ShoppingCart/components/Card.js +++ b/src/ShoppingCart/components/Card.js @@ -21,26 +21,32 @@ const CardPriceStyle = styled.div` align-items: flex-end; `; -const RemoveStyle = styled.a` +const ButtonStyle = styled.a` color: black; + font-size: 25px; cursor: pointer; &:hover { text-decoration: underline; } `; -export const Card = ({ name, img, type, price, quantity, onRemove }) => ( +export const Card = ({ name, img, type, price, quantity, onAdd, onRemove }) => ( <> {name}
    {name}

    {type}

    - Remove + + + + + + - +

    {quantity}

    -

    {price}

    +

    {price * quantity}

    diff --git a/src/ShoppingCart/components/Total.js b/src/ShoppingCart/components/Total.js index 7900a0c..3f7c64f 100644 --- a/src/ShoppingCart/components/Total.js +++ b/src/ShoppingCart/components/Total.js @@ -1,3 +1,4 @@ +import { useHistory } from "react-router-dom"; import styled from "styled-components"; import { HRStyle } from "./Hr"; @@ -21,26 +22,32 @@ const CheckoutButton = styled.button` border: 0; cursor: pointer; padding: 24px 0; - align-self: end; &:hover { opacity: 0.8; } `; -export const Total = ({ total }) => ( -
    -

    Total

    - - Subtotal - {(total * 0.8).toFixed(2)} - - - - Total (VAT included) - {total} - - - Checkout -
    -); +export const Total = ({ total }) => { + const history = useHistory(); + + const redirect = () => { + history.push(`/checkout`); + }; + return ( +
    +

    Total

    + + Subtotal + {(total * 0.8).toFixed(2)} + + + + Total (VAT included) + {total} + + + Checkout +
    + ); +}; diff --git a/src/common/PokemonCard/PokemonCard.jsx b/src/common/PokemonCard/PokemonCard.jsx index 9e12d63..aeac218 100644 --- a/src/common/PokemonCard/PokemonCard.jsx +++ b/src/common/PokemonCard/PokemonCard.jsx @@ -45,15 +45,11 @@ const DetailsButton = styled.button` } `; -export const PokemonCard = ({ - name, image, click, price, -}) => ( - +export const PokemonCard = ({ name, image, click, price }) => ( + {name} {name} - {price || '???'} € + {price || "???"} € Details ); diff --git a/src/common/pokemonStorage.js b/src/common/pokemonStorage.js index 7fb7ea4..2547ac2 100644 --- a/src/common/pokemonStorage.js +++ b/src/common/pokemonStorage.js @@ -1,9 +1,34 @@ const STORAGE_KEY = "cart"; +const COUNTER_KEY = "counter"; +const ORDER_KEY = "order"; + +export const getOrderDetails = () => { + try { + const orderStorage = localStorage.getItem(ORDER_KEY); + return orderStorage ? JSON.parse(orderStorage) : []; + } catch (e) { + return []; + } +}; export const getCartItems = () => { try { const cartStorage = localStorage.getItem(STORAGE_KEY); - return JSON.parse(cartStorage); + return cartStorage ? JSON.parse(cartStorage) : []; + } catch (e) { + return []; + } +}; + +export const getCounter = () => { + try { + const counterStorage = localStorage.getItem(COUNTER_KEY); + if (counterStorage) { + /* eslint-disable */ + const count = parseInt(counterStorage); + return count; + } + return 0; } catch (e) { return []; } @@ -11,13 +36,50 @@ export const getCartItems = () => { export const addToCart = (item) => { const cartStorage = getCartItems(); + const currentCounter = getCounter(); + const foundIndex = cartStorage.findIndex((itm) => itm.name === item.name); + if (foundIndex > -1) { + /* eslint-disable */ + let indexValue = cartStorage[foundIndex]; + item["quantity"] = indexValue["quantity"] + 1; + cartStorage.splice(foundIndex, 1); + } cartStorage.push(item); localStorage.setItem(STORAGE_KEY, JSON.stringify(cartStorage)); + localStorage.setItem(COUNTER_KEY, currentCounter + 1); + return cartStorage; +}; + +export const addOrderDetails = (orderDetail) => { + localStorage.removeItem(ORDER_KEY); + localStorage.setItem(ORDER_KEY, JSON.stringify(orderDetail)); }; export const removeFromCart = (name) => { const cartStorage = getCartItems(); - const filteredCart = cartStorage.filter((c) => c.name !== name); - localStorage.setItem(STORAGE_KEY, JSON.stringify(filteredCart)); - return filteredCart; + const currentCounter = getCounter(); + console.log("currentCounter", currentCounter); + if (currentCounter > 0) { + localStorage.setItem(COUNTER_KEY, currentCounter - 1); + } + const foundIndex = cartStorage.findIndex((itm) => itm.name === name); + if (foundIndex > -1) { + /* eslint-disable */ + if (cartStorage[foundIndex]["quantity"] > 1) { + cartStorage[foundIndex]["quantity"] = + cartStorage[foundIndex]["quantity"] - 1; + localStorage.setItem(STORAGE_KEY, JSON.stringify(cartStorage)); + return cartStorage; + } else { + const filteredCart = cartStorage.filter((c) => c.name !== name); + localStorage.setItem(STORAGE_KEY, JSON.stringify(filteredCart)); + return filteredCart; + } + } +}; + +export const emptyStorage = () => { + localStorage.removeItem(ORDER_KEY); + localStorage.removeItem(COUNTER_KEY); + localStorage.removeItem(STORAGE_KEY); };