skeleton for cart
This commit is contained in:
@@ -122,4 +122,13 @@ nav {
|
|||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 0.8rem;
|
padding: 0.8rem;
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cart styles
|
||||||
|
.cart-item-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0 2rem;
|
||||||
|
background-color: white;
|
||||||
|
width: 75vw;
|
||||||
}
|
}
|
||||||
@@ -8,9 +8,10 @@ import Products from './components/Products/Products';
|
|||||||
import LoginForm from './components/User/LoginForm';
|
import LoginForm from './components/User/LoginForm';
|
||||||
import Register from './components/User/Register';
|
import Register from './components/User/Register';
|
||||||
import UserProfile from './components/User/UserProfile';
|
import UserProfile from './components/User/UserProfile';
|
||||||
|
import ProductPage from './components/Products/ProductPage';
|
||||||
|
import Cart from './components/Cart/Cart';
|
||||||
|
|
||||||
import './App.scss'
|
import './App.scss'
|
||||||
import ProductPage from './components/Products/ProductPage';
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [state, dispatch] = useReducer(reducer, initialState);
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
@@ -26,6 +27,7 @@ function App() {
|
|||||||
<Route path="/users/:userID" element={<UserProfile profile={state.user.id} />} />
|
<Route path="/users/:userID" element={<UserProfile profile={state.user.id} />} />
|
||||||
<Route path="/register" element={<Register/>} />
|
<Route path="/register" element={<Register/>} />
|
||||||
<Route path="/products/" element={<Products />} />
|
<Route path="/products/" element={<Products />} />
|
||||||
|
<Route path="/cart/" element={<Cart />} />
|
||||||
<Route path="/products/:productID" element={<ProductPage />} />
|
<Route path="/products/:productID" element={<ProductPage />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</AppContext.Provider>
|
</AppContext.Provider>
|
||||||
|
|||||||
@@ -1,7 +1,37 @@
|
|||||||
|
import { useContext, useEffect, useState } from "react";
|
||||||
|
import { AppContext } from "../../store/store";
|
||||||
|
import { Product } from '../../types/main';
|
||||||
|
import Page from "../../util/Page";
|
||||||
|
import CartItem from "./CartItem";
|
||||||
|
|
||||||
function Cart() {
|
function Cart() {
|
||||||
|
const [state, dispatch] = useContext(AppContext);
|
||||||
|
const [contents, setContents] = useState<JSX.Element>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setContents(
|
||||||
|
state.cart.contents.map((product: Product) => <CartItem product={product} />)
|
||||||
|
)
|
||||||
|
}, [state, setContents]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(contents);
|
||||||
|
}, [contents]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Page>
|
||||||
</>
|
{
|
||||||
|
state.user.firstName ?
|
||||||
|
|
||||||
|
<h1>Hello, {state.user.firstName}!</h1>
|
||||||
|
:
|
||||||
|
<h1>Your cart is empty! Please <a href='/login'>log in</a> to build your own.</h1>
|
||||||
|
}
|
||||||
|
|
||||||
|
<section id="cart-contents">
|
||||||
|
{contents || null}
|
||||||
|
</section>
|
||||||
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
function CartItem() {
|
function CartItem({ product }: any) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="cart-item-panel">
|
||||||
</>
|
<strong>{product.name}</strong>
|
||||||
|
<p>{product.price}</p>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,13 @@ function NavBar() {
|
|||||||
<button onClick={handleSearch}>Search</button>
|
<button onClick={handleSearch}>Search</button>
|
||||||
<button onClick={() => console.log(state)}>Render</button>
|
<button onClick={() => console.log(state)}>Render</button>
|
||||||
</div>
|
</div>
|
||||||
{loggedIn ? <button onClick={() => navigate(`/users/${state.user.id}`)}>{profText}</button> : <button onClick={() => navigate("/login")}>Log In</button>}
|
{loggedIn ?
|
||||||
|
<>
|
||||||
|
<button onClick={() => navigate(`/users/${state.user.id}`)}>{profText}</button>
|
||||||
|
<button onClick={() => navigate('/cart')}>Your cart</button>
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
<button onClick={() => navigate("/login")}>Log In</button>}
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Route from 'react-router-dom';
|
import { addToCart } from "../../util/helpers";
|
||||||
import ProductPage from "./ProductPage";
|
import { AppContext } from "../../store/store";
|
||||||
|
|
||||||
export default function ProductCard({ productData }: any) {
|
export default function ProductCard({ productData }: any) {
|
||||||
const { name, category, description, price, id } = productData;
|
const { name, category, description, price, id } = productData;
|
||||||
|
const [state, dispatch] = useContext(AppContext);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -15,7 +17,14 @@ export default function ProductCard({ productData }: any) {
|
|||||||
<p>Price: {`$${price}` || "Free, apparently!"}</p>
|
<p>Price: {`$${price}` || "Free, apparently!"}</p>
|
||||||
<div className="product-options">
|
<div className="product-options">
|
||||||
<button onClick={() => navigate(`/products/${id}`)}>More info</button>
|
<button onClick={() => navigate(`/products/${id}`)}>More info</button>
|
||||||
<button>Add to Cart</button>
|
|
||||||
|
{
|
||||||
|
state.user.headers && state.user.headers.authenticated ?
|
||||||
|
<button onClick={() => addToCart(productData, dispatch)}>Add to Cart</button>
|
||||||
|
:
|
||||||
|
<button onClick={() => navigate('/login')}>Login to add to your cart</button>
|
||||||
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default function ProductPage() {
|
|||||||
|
|
||||||
<p>(a photo here)</p>
|
<p>(a photo here)</p>
|
||||||
<p>{info.description}</p>
|
<p>{info.description}</p>
|
||||||
<p>Price: {info.price}</p>
|
<p>Price: ${info.price}</p>
|
||||||
</Page>
|
</Page>
|
||||||
: <></>
|
: <></>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useReducer, useState } from "react";
|
import { useEffect, useReducer, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import { initialState, reducer } from "../../store/store";
|
import { initialState, reducer } from "../../store/store";
|
||||||
import { ActionType, emptySessionHeader } from "../../store/store_types";
|
import { ActionType, emptySessionHeader } from "../../store/store_types";
|
||||||
import { userInfo } from '../../types/main';
|
import { userInfo } from '../../types/main';
|
||||||
@@ -16,6 +17,7 @@ function Register() {
|
|||||||
headers: emptySessionHeader
|
headers: emptySessionHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
const [state, dispatch] = useReducer(reducer, initialState);
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
const [userInput, setUserInput] = useState(formInitialState);
|
const [userInput, setUserInput] = useState(formInitialState);
|
||||||
const [warningText, setWarningText] = useState('initial');
|
const [warningText, setWarningText] = useState('initial');
|
||||||
@@ -58,6 +60,7 @@ function Register() {
|
|||||||
|
|
||||||
if (register.ok) {
|
if (register.ok) {
|
||||||
setUserInput(formInitialState);
|
setUserInput(formInitialState);
|
||||||
|
navigate('/');
|
||||||
} else {
|
} else {
|
||||||
console.log('Something went wrong');
|
console.log('Something went wrong');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,18 @@ export const reducer = (state: appState, action: userAction) => {
|
|||||||
...state,
|
...state,
|
||||||
user: payload
|
user: payload
|
||||||
}
|
}
|
||||||
|
case ActionType.ADDTOCART:
|
||||||
|
let updatedContents = state.cart.contents;
|
||||||
|
console.log(action.payload);
|
||||||
|
updatedContents.push(action.payload);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
cart: {
|
||||||
|
...state.cart,
|
||||||
|
contents: updatedContents
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ export enum ActionType {
|
|||||||
REGISTERNEW,
|
REGISTERNEW,
|
||||||
UPDATEONE,
|
UPDATEONE,
|
||||||
SEARCH,
|
SEARCH,
|
||||||
USERLOGIN
|
USERLOGIN,
|
||||||
|
ADDTOCART
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface userAction {
|
export interface userAction {
|
||||||
|
|||||||
2
client/src/types/main.d.ts
vendored
2
client/src/types/main.d.ts
vendored
@@ -7,7 +7,7 @@ export type userInfo = {
|
|||||||
email: string
|
email: string
|
||||||
id?: number
|
id?: number
|
||||||
|
|
||||||
// NOTE: userInfo.name is deprecated
|
// NOTE: userInfo.name => displayName?
|
||||||
name?: string
|
name?: string
|
||||||
password: string
|
password: string
|
||||||
verifyPassword?: string
|
verifyPassword?: string
|
||||||
|
|||||||
7
client/src/util/helpers.ts
Normal file
7
client/src/util/helpers.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ActionType, userAction } from "../store/store_types";
|
||||||
|
import { Product } from "../types/main";
|
||||||
|
|
||||||
|
export const addToCart = (productData: Product, dispatch: React.Dispatch<userAction>): any => {
|
||||||
|
dispatch({ type: ActionType.ADDTOCART, payload: productData });
|
||||||
|
}
|
||||||
0
swagger.yml
Normal file
0
swagger.yml
Normal file
Reference in New Issue
Block a user