incorporating basic logic for viewing distinct products
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
export default function ProductCard() {
|
||||
export default function ProductCard({ productData }: any) {
|
||||
const { name, category, description, price, id } = productData;
|
||||
|
||||
return (
|
||||
<div className="card product-card">
|
||||
<div className="photo"></div>
|
||||
<h1>Product name</h1>
|
||||
<p>$4.99</p>
|
||||
<p>This is a mini description of the product</p>
|
||||
<button>Add to Cart</button>
|
||||
<div className="card product-card" key={`product-id-${id}`}>
|
||||
<div className="product-photo"></div>
|
||||
<h1>{name}</h1>
|
||||
<p>Category: {category}</p>
|
||||
<p>{description}</p>
|
||||
<p>Price: {`$${price}` || "Free, apparently!"}</p>
|
||||
<div className="product-options">
|
||||
<button>More info</button>
|
||||
<button>Add to Cart</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,14 +1,47 @@
|
||||
import Page from "../../util/Page";
|
||||
import ProductCard from "./ProductCard";
|
||||
import { getAllProducts } from '../../util/apiUtils';
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
type ProductResponse = {
|
||||
category: string,
|
||||
category_id?: number,
|
||||
description: string,
|
||||
id: number,
|
||||
inventory: number,
|
||||
minidescription?: string,
|
||||
name: string,
|
||||
price: string
|
||||
}
|
||||
|
||||
function Products() {
|
||||
const [productData, setProductData] = useState([]);
|
||||
const [productFeed, setProductFeed] = useState<Array<JSX.Element>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
getAllProducts().then(res => setProductData(res));
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!productData) return;
|
||||
console.log(productData);
|
||||
|
||||
let results = productData.map((each: ProductResponse) => {
|
||||
return <ProductCard key={each.id} productData={each} />
|
||||
});
|
||||
|
||||
setProductFeed(results);
|
||||
}, [productData]);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<h1>Found 2 products</h1>
|
||||
<h1>Found {productFeed.length} products</h1>
|
||||
<div className="filter-results">
|
||||
|
||||
</div>
|
||||
|
||||
<div className="products-results">
|
||||
<ProductCard/>
|
||||
<ProductCard/>
|
||||
{ productFeed || <p>Loading...</p> }
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
|
||||
@@ -16,7 +16,6 @@ function LoginForm() {
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [showPass, setShowPass] = useState(PassVisible.hide);
|
||||
const [toDispatch, setToDispatch] = useState<userInfo>();
|
||||
|
||||
const displaySession = async () => {
|
||||
if (username === '' || password === '') return;
|
||||
@@ -27,21 +26,18 @@ function LoginForm() {
|
||||
if (json) {
|
||||
const { session, userProfile } = json;
|
||||
let thisUser: userInfo = {
|
||||
firstName: userProfile.first_name,
|
||||
lastName: userProfile.last_name,
|
||||
id: userProfile.id,
|
||||
email: userProfile.email,
|
||||
password: userProfile.password,
|
||||
headers: session
|
||||
}
|
||||
|
||||
setToDispatch(thisUser);
|
||||
dispatch({ type: ActionType.USERLOGIN, payload: thisUser });
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!toDispatch) return;
|
||||
dispatch({ type: ActionType.USERLOGIN, payload: toDispatch });
|
||||
}, [toDispatch]);
|
||||
|
||||
return (
|
||||
<Page classes="login light-page">
|
||||
<h1>Welcome back to my store!</h1>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { emptySessionHeader } from "../../store/store_types";
|
||||
import { useEffect, useReducer, useState } from "react";
|
||||
import { initialState, reducer } from "../../store/store";
|
||||
import { ActionType, emptySessionHeader } from "../../store/store_types";
|
||||
import { userInfo } from '../../types/main';
|
||||
import { registerNewUser } from "../../util/apiUtils";
|
||||
import { handleLogin, registerNewUser, unwrapLogin } from "../../util/apiUtils";
|
||||
import Page from "../../util/Page";
|
||||
|
||||
function Register() {
|
||||
@@ -15,6 +16,7 @@ function Register() {
|
||||
headers: emptySessionHeader
|
||||
}
|
||||
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
const [userInput, setUserInput] = useState(formInitialState);
|
||||
const [warningText, setWarningText] = useState('initial');
|
||||
|
||||
@@ -50,9 +52,15 @@ function Register() {
|
||||
// allows registration submission if warning text has correct value and userData is defined with all required values
|
||||
const handleRegistration = async () => {
|
||||
if (userInput === formInitialState) return;
|
||||
warningText === "Conditions met!" && await registerNewUser(userInput);
|
||||
if (warningText !== "Conditions met!") return;
|
||||
|
||||
let register = await registerNewUser(userInput);
|
||||
|
||||
setUserInput(formInitialState);
|
||||
if (register.ok) {
|
||||
setUserInput(formInitialState);
|
||||
} else {
|
||||
console.log('Something went wrong');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -73,7 +81,7 @@ function Register() {
|
||||
|
||||
<div className="form-row">
|
||||
<label htmlFor="email-register">Email address:</label>
|
||||
<input type="email" id="email-register" value={userInput.email} onChange={(e) => setUserInput({...userInput, email: e.target.value})}/>
|
||||
<input required type="email" id="email-register" value={userInput.email} onChange={(e) => setUserInput({...userInput, email: e.target.value})}/>
|
||||
</div>
|
||||
|
||||
<p style={(warningText === 'initial') ? {display: 'none'} : {display: 'block'}}>{warningText}</p>
|
||||
@@ -82,13 +90,13 @@ function Register() {
|
||||
<label htmlFor="password-register" style={(warningText && warningText !== 'Conditions met!') ? {color: 'red'} : {color: 'green'}}>
|
||||
Password:
|
||||
</label>
|
||||
<input type="password" id="password-register" value={userInput.password} onChange={(e) => setUserInput({...userInput, password: e.target.value})}/>
|
||||
<input required type="password" id="password-register" value={userInput.password} onChange={(e) => setUserInput({...userInput, password: e.target.value})}/>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="password-verify" style={(warningText && warningText !== 'Conditions met!') ? {color: 'red'} : {color: 'green'}}>
|
||||
Re-enter password:
|
||||
</label>
|
||||
<input type="password" id="password-verify" value={userInput.verifyPassword} onChange={(e) => setUserInput({...userInput, verifyPassword: e.target.value})}/>
|
||||
<input required type="password" id="password-verify" value={userInput.verifyPassword} onChange={(e) => setUserInput({...userInput, verifyPassword: e.target.value})}/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useContext, useEffect } from "react"
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useContext } from "react"
|
||||
import { AppContext } from "../../store/store"
|
||||
|
||||
import Page from "../../util/Page";
|
||||
@@ -7,18 +6,10 @@ import Page from "../../util/Page";
|
||||
export default function UserProfile(profile: any): JSX.Element {
|
||||
const [state, dispatch] = useContext(AppContext);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!state.user.headers.authenticated) {
|
||||
// console.log('bad');
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
if (state.user) return (
|
||||
<Page classes="light-page">
|
||||
<h1>User Profile</h1>
|
||||
<h2>Thanks for supporting us{`, ${state.user.name}!` || '!'}</h2>
|
||||
<h2>Thanks for supporting us{`, ${state.user.firstName}!` || '!'}</h2>
|
||||
<h2>{state.user.id || 'Profile not found'}</h2>
|
||||
<h3>{state.user.email}</h3>
|
||||
|
||||
@@ -29,5 +20,7 @@ export default function UserProfile(profile: any): JSX.Element {
|
||||
<button>Profile Settings</button>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
);
|
||||
|
||||
return (<></>)
|
||||
}
|
||||
@@ -19,15 +19,11 @@ export const reducer = (state: appState, action: userAction) => {
|
||||
case ActionType.UPDATEONE:
|
||||
return state;
|
||||
case ActionType.SEARCH:
|
||||
console.log(payload);
|
||||
|
||||
return {
|
||||
...state,
|
||||
searchTerm: payload
|
||||
}
|
||||
case ActionType.USERLOGIN:
|
||||
console.log(payload);
|
||||
|
||||
return {
|
||||
...state,
|
||||
user: payload
|
||||
|
||||
@@ -3,6 +3,7 @@ import { userInfo, Cart } from '../types/main';
|
||||
// type definitions for reducer
|
||||
export enum ActionType {
|
||||
GETALL,
|
||||
GETPROFILE,
|
||||
GETCATEGORY,
|
||||
REGISTERNEW,
|
||||
UPDATEONE,
|
||||
|
||||
@@ -24,6 +24,7 @@ export const registerNewUser = async (user: userInfo) => {
|
||||
});
|
||||
|
||||
if (serverCall.ok) console.log('User added successfully.');
|
||||
return serverCall;
|
||||
}
|
||||
|
||||
export const handleLogin = async (email: string, password: string) => {
|
||||
@@ -37,3 +38,21 @@ export const handleLogin = async (email: string, password: string) => {
|
||||
|
||||
return serverCall;
|
||||
}
|
||||
|
||||
export const unwrapLogin = async (email: string, password: string) => {
|
||||
const response = await handleLogin(email, password);
|
||||
const { session, userProfile } = await response.json();
|
||||
|
||||
return { session, userProfile };
|
||||
}
|
||||
|
||||
export const getAllProducts = async () => {
|
||||
let serverCall = await fetch('http://localhost:8088/products', {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}).then(res => res.json());
|
||||
|
||||
return serverCall;
|
||||
}
|
||||
|
||||
31
package-lock.json
generated
31
package-lock.json
generated
@@ -19,7 +19,11 @@
|
||||
"oauth2-server": "^3.1.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pg": "^8.7.3"
|
||||
"pg": "^8.7.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/uuid": "^8.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp": {
|
||||
@@ -41,6 +45,12 @@
|
||||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@@ -1581,6 +1591,14 @@
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@@ -1647,6 +1665,12 @@
|
||||
"tar": "^6.1.11"
|
||||
}
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@@ -2804,6 +2828,11 @@
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
"oauth2-server": "^3.1.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pg": "^8.7.3"
|
||||
"pg": "^8.7.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/uuid": "^8.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user