Commit 4d719d79 authored by John Lam's avatar John Lam

fix merge conflict

parents 9068a7f1 68d3275f
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from "react";
import { Redirect, Switch } from "react-router"; import { Redirect, Switch } from "react-router";
import AuthRoute from "./AuthRoute"; import AuthRoute from "./AuthRoute";
import ProductForm from "./ProductForm"; import ProductForm from "./ProductForm";
import PromotionNewFormComponent from './promotionforms/PromotionNewFormComponent'
import ProductGrid from "./ProductGrid"; import ProductGrid from "./ProductGrid";
import {getAllProducts} from "../actions/apiRequests.js" import { getAllProducts } from "../actions/apiRequests.js";
import PromotionNewFormComponent from "./promotionforms/PromotionNewFormComponent";
export default function Main() { export default function Main() {
const [productData, setproductData] = useState([]); const [productData, setproductData] = useState([]);
...@@ -17,23 +16,30 @@ export default function Main() { ...@@ -17,23 +16,30 @@ export default function Main() {
const loadProducts = async (event) => { const loadProducts = async (event) => {
const data = await getAllProducts(); const data = await getAllProducts();
setproductData(data); setproductData(data);
} };
return ( return (
<div> <div>
<Switch> <Switch>
<AuthRoute exact path="/products/new"> <AuthRoute exact path="/products/new">
<ProductForm /> <ProductForm method="POST" />
</AuthRoute> </AuthRoute>
<AuthRoute exact path="/promos/new" component={PromotionNewFormComponent}>NEW PROMO</AuthRoute> <AuthRoute exact path="/products/edit/:sku">
<AuthRoute exact path="/products"> <ProductForm method="PUT" />
<ProductGrid productData={productData} />
</AuthRoute> </AuthRoute>
<AuthRoute
exact
path="/promos/new"
component={PromotionNewFormComponent}
></AuthRoute>
<AuthRoute exact path="/products" component={ProductGrid}></AuthRoute>
<AuthRoute path="/promos">PROMOS</AuthRoute> <AuthRoute path="/promos">PROMOS</AuthRoute>
<AuthRoute exact path="/"> <AuthRoute exact path="/">
<Redirect to="/products" /> <Redirect to="/products" />
</AuthRoute> </AuthRoute>
<AuthRoute >404 PAGE</AuthRoute> <AuthRoute>
<h1>404 Page Not Found</h1>
</AuthRoute>
</Switch> </Switch>
</div> </div>
); );
......
import React from 'react' import React, { useState } from "react";
import './../styles/Product.css' import "./../styles/Product.css";
import { Modal, Button, Alert } from "react-bootstrap";
export default function Product({product}) { export default function Product({ product }) {
const [show, setShow] = useState(false);
const [showConfirm, setShowConfirm] = useState(false);
const handleClose = () => {
setShow(false);
handleCloseConfirm();
};
const handleShow = () => setShow(true);
const handleShowConfirm = () => setShowConfirm(true);
const handleCloseConfirm = () => setShowConfirm(false);
return ( return (
<div> <div>
<div className="img-container"> <div className="img-container" onClick={handleShow}>
<img src={product.productImageUrl} alt={product.productName}/> <img
className="grid-img"
src={product.productImageUrl}
alt={product.productName}
/>
</div> </div>
<div className="prod-info"> <div className="prod-info">
<h5>{product.productName}</h5> <h5>{product.productName}</h5>
{product.sku}<br/> {product.sku}
${product.price}<br/> <br />${product.price}
<br />
In Stock: {product.stock} In Stock: {product.stock}
</div> </div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{product.productName}</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="modal-img">
<img src={product.productImageUrl} alt={product.productName} />
</div>
<h5>{product.sku}</h5>${product.price}
<br />
{product.productDescription}
<br />
In Stock: {product.stock}
</Modal.Body>
<Modal.Footer>
<Button
variant="danger"
className="float-left"
onClick={handleShowConfirm}
>
Delete product
</Button>
<Button variant="primary" href={`/products/edit/${product.sku}`}>
Edit Product
</Button>
<Alert show={showConfirm} variant="danger">
<h5> Are you sure?</h5>
<Button variant="secondary" onClick={handleCloseConfirm}>
Cancel
</Button>
&nbsp;&nbsp;
<Button variant="danger">Yes, delete</Button>
</Alert>
</Modal.Footer>
</Modal>
</div> </div>
) );
} }
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import { useHistory, useLocation } from "react-router"; import { useHistory, useParams } from "react-router";
import emptyProduct from "../emptProduct";
const emptyForm = { const emptyForm = {
sku: "", ...emptyProduct,
upc: "", imageFile: "",
productName: "",
brand: "",
category: "",
price: 0.0,
availableStock: 0,
productDescription: "",
productImageUrl: "",
productImage: ""
}; };
ProductForm.defaultProps = { ProductForm.defaultProps = {
...@@ -19,15 +12,34 @@ ProductForm.defaultProps = { ...@@ -19,15 +12,34 @@ ProductForm.defaultProps = {
}; };
export default function ProductForm(props) { export default function ProductForm(props) {
const { product } = props; const { method } = props;
const [form, setForm] = useState(product); const [form, setForm] = useState({ ...emptyForm });
const [imageMode, setImageMode] = useState("url");
const [errors, setErrors] = useState([]); const [errors, setErrors] = useState([]);
const history = useHistory(); const history = useHistory();
const { productId } = useParams("productId");
useEffect(() => {
fetch(`http://localhost:8080/api/products/${productId}/`).then((res) => {
if (res.ok) {
console.log(res);
res.json().then((data) => {
Object.keys(data).forEach((key) => {
if (data[key] === null) {
data[key] = "";
}
});
console.log(data);
setForm({ ...data, availableStock: data.stock });
});
}
});
}, [productId]);
const validate = () => { const validate = () => {
setErrors([]); setErrors([]);
const errs = []; const errs = [];
console.log(form)
if (form.sku.length < 3) { if (form.sku.length < 3) {
errs.push("SKU must be at least 3 characters"); errs.push("SKU must be at least 3 characters");
} }
...@@ -56,11 +68,20 @@ export default function ProductForm(props) { ...@@ -56,11 +68,20 @@ export default function ProductForm(props) {
const onSubmit = (e) => { const onSubmit = (e) => {
e.preventDefault(); e.preventDefault();
validate(); validate();
if (imageMode === "url") {
delete form.imageFile;
} else {
delete form.prodImgUrl;
}
if (errors.length === 0) { if (errors.length === 0) {
// console.log(form); // console.log(form);
fetch("http://localhost:8080/api/products", { const url =
method: "POST", method === "PUT"
? `${Config.inventoryUrl}/${sku}`
: `${Config.inventoryUrl}`;
fetch(url, {
method,
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
...@@ -100,11 +121,13 @@ export default function ProductForm(props) { ...@@ -100,11 +121,13 @@ export default function ProductForm(props) {
SKU SKU
</label> </label>
<input <input
disabled={method === "PUT" ? true : false}
required required
name="sku" name="sku"
type="text" type="text"
className="form-control" className="form-control"
id="productSku" id="productSku"
disabled={method === "PUT" ? true : false}
value={form.sku} value={form.sku}
onChange={(e) => setForm({ ...form, sku: e.target.value })} onChange={(e) => setForm({ ...form, sku: e.target.value })}
/> />
...@@ -137,7 +160,9 @@ export default function ProductForm(props) { ...@@ -137,7 +160,9 @@ export default function ProductForm(props) {
className="form-control" className="form-control"
id="productName" id="productName"
value={form.productName} value={form.productName}
onChange={(e) => setForm({ ...form, productName: e.target.value })} onChange={(e) =>
setForm({ ...form, productName: e.target.value })
}
/> />
</div> </div>
<div> <div>
...@@ -170,17 +195,19 @@ export default function ProductForm(props) { ...@@ -170,17 +195,19 @@ export default function ProductForm(props) {
</div> </div>
</div> </div>
<div className="col-6"> <div className="col-6">
<label htmlFor="productDescription" className="form-label"> <label htmlFor="productDesc" className="form-label">
Description Description
</label> </label>
<textarea <textarea
name="productDescription" name="productDesciption"
id="productDescription" id="productDesc"
cols="40" cols="40"
rows="7" rows="7"
className="form-control" className="form-control"
value={form.productDescription} value={form.productDescription}
onChange={(e) => setForm({ ...form, productDescription: e.target.value })} onChange={(e) =>
setForm({ ...form, productDescription: e.target.value })
}
></textarea> ></textarea>
</div> </div>
</div> </div>
...@@ -204,8 +231,9 @@ export default function ProductForm(props) { ...@@ -204,8 +231,9 @@ export default function ProductForm(props) {
Stock Stock
</label> </label>
<input <input
disabled={method === "PUT" ? true : false}
required required
name="stock" name="availableStock"
type="number" type="number"
className="form-control" className="form-control"
id="stock" id="stock"
...@@ -214,28 +242,61 @@ export default function ProductForm(props) { ...@@ -214,28 +242,61 @@ export default function ProductForm(props) {
/> />
</div> </div>
</div> </div>
{imageMode === "upload" ? (
<div className="row mt-3"> <div className="row mt-3">
<div>
<label htmlFor="productImage" className="form-label"> <label htmlFor="productImage" className="form-label">
Product Image Image File
</label> </label>
<input
id="productImageUrl"
name="productImageUrl"
className="form-control form-control-lg"
type="url"
placeholder="Enter image URL here or upload image below..."
value={form.productImageUrl}
onChange={(e) => setForm({ ...form, productImageUrl: e.target.value, productImage:""})}
></input>
<input <input
id="productImage" id="productImage"
name="productImage" name="imageFile"
className="form-control form-control-lg" className="form-control form-control-lg"
type="file" type="file"
value={form.productImage} value={form.imageFile}
onChange={(e) => setForm({ ...form, productImage: e.target.value, productImageUrl:"" })} onChange={(e) =>
setForm({ ...form, imageFile: e.target.value })
}
></input> ></input>
<button
type="button"
className="btn btn-outline-primary mt-3"
onClick={() => {
setForm({ ...form, imageFile: "" });
setImageMode("url");
}}
>
Specify Image URL
</button>
</div>
</div>
) : null}
{imageMode === "url" ? (
<div className="row mt-3">
<div>
<label htmlFor="prodImgUrl" className="form-label">
Image URL
</label>
<input
name="productImageUrl"
type="text"
className="form-control"
id="prodImgUrl"
value={form.productImageUrl}
onChange={(e) =>
setForm({ ...form, productImageUrl: e.target.value })
}
/>
<button
type="button"
className="btn btn-outline-primary mt-3"
onClick={() => setImageMode("upload")}
>
Upload Image
</button>
</div> </div>
</div>
) : null}
<div className="row mt-3"> <div className="row mt-3">
<div className="col-12"> <div className="col-12">
......
import React from "react"; import React, { useEffect, useState } from "react";
import Product from "./Product.jsx"; import Product from "./Product.jsx";
import { Col, Container, Row } from "react-bootstrap"; import { Col, Container, Row } from "react-bootstrap";
import "./../styles/ProductGrid.css"; import "./../styles/ProductGrid.css";
import Config from "../config.js";
import { Link } from "react-router-dom";
export default function ProductGrid({ productData }) { export default function ProductGrid({ productData }) {
const [products, setProducts] = useState([]);
const fetchProducts = async () => {
const res = await fetch(`${Config.inventoryUrl}`);
if (res.ok) {
const data = await res.json();
setProducts([...data]);
}
};
useEffect(() => fetchProducts(), []);
return ( return (
<div> <div class="container flex-column d-flex justify-content-center">
<h1 id="title" className="text-center" >Inventory</h1> <div className="container mt-3 d-flex justify-content-between align-items-center">
<Container id="prod-grid" className="mt-3"> <h1 id="title" className="text-center">
Inventory
</h1>
<Link type="link" className="btn btn-success" to="/products/new">
+ New Product
</Link>
</div>
<Container id="prod-grid" className="mt-3 mx-auto">
<Row xs={1} sm={2} md={3} lg={4}> <Row xs={1} sm={2} md={3} lg={4}>
{productData.map((product) => { {products.map((product) => {
return ( return (
<Col key={product.sku}> <Col key={product.sku}>
<Product product={product} /> <Product product={product} />
......
const emptyProduct = {
sku: "",
upc: "",
productName: "",
brand: "",
category: "",
price: 0.0,
availableStock: 0,
productDesciption: "",
productImageUrl: "",
};
export default emptyProduct;
img {
max-width: 100%;
max-height: 250px;
}
.img-container{ .img-container{
position:relative; position:relative;
overflow:hidden; overflow:hidden;
padding-bottom:100%; padding-bottom:100%;
} }
img { .grid-img {
position: absolute; position: absolute;
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
...@@ -11,3 +16,12 @@ img { ...@@ -11,3 +16,12 @@ img {
left: 50%; left: 50%;
transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%);
} }
.modal-img {
display: flex;
justify-content: center;
}
.alert{
width: 100%;
}
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment