Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
inventory-promotion-react
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ascend
inventory-promotion-react
Commits
4d719d79
Commit
4d719d79
authored
May 10, 2021
by
John Lam
Browse files
Options
Browse Files
Download
Plain Diff
fix merge conflict
parents
9068a7f1
68d3275f
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
10859 additions
and
7642 deletions
+10859
-7642
Main.jsx
src/component/Main.jsx
+16
-10
Product.jsx
src/component/Product.jsx
+69
-13
ProductForm.jsx
src/component/ProductForm.jsx
+106
-45
ProductGrid.jsx
src/component/ProductGrid.jsx
+27
-5
config.js
src/config.js
+1
-1
emptProduct.js
src/emptProduct.js
+13
-0
Product.css
src/styles/Product.css
+15
-1
yarn.lock
yarn.lock
+10612
-7567
No files found.
src/component/Main.jsx
View file @
4d719d79
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
React
,
{
useState
,
useEffect
}
from
"react"
;
import
{
Redirect
,
Switch
}
from
"react-router"
;
import
AuthRoute
from
"./AuthRoute"
;
import
ProductForm
from
"./ProductForm"
;
import
PromotionNewFormComponent
from
'./promotionforms/PromotionNewFormComponent'
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
()
{
const
[
productData
,
setproductData
]
=
useState
([]);
...
...
@@ -17,23 +16,30 @@ export default function Main() {
const
loadProducts
=
async
(
event
)
=>
{
const
data
=
await
getAllProducts
();
setproductData
(
data
);
}
}
;
return
(
<
div
>
<
Switch
>
<
AuthRoute
exact
path=
"/products/new"
>
<
ProductForm
/>
<
ProductForm
method=
"POST"
/>
</
AuthRoute
>
<
AuthRoute
exact
path=
"/promos/new"
component=
{
PromotionNewFormComponent
}
>
NEW PROMO
</
AuthRoute
>
<
AuthRoute
exact
path=
"/products"
>
<
ProductGrid
productData=
{
productData
}
/>
<
AuthRoute
exact
path=
"/products/edit/:sku"
>
<
ProductForm
method=
"PUT"
/>
</
AuthRoute
>
<
AuthRoute
exact
path=
"/promos/new"
component=
{
PromotionNewFormComponent
}
></
AuthRoute
>
<
AuthRoute
exact
path=
"/products"
component=
{
ProductGrid
}
></
AuthRoute
>
<
AuthRoute
path=
"/promos"
>
PROMOS
</
AuthRoute
>
<
AuthRoute
exact
path=
"/"
>
<
Redirect
to=
"/products"
/>
</
AuthRoute
>
<
AuthRoute
>
404 PAGE
</
AuthRoute
>
<
AuthRoute
>
<
h1
>
404 Page Not Found
</
h1
>
</
AuthRoute
>
</
Switch
>
</
div
>
);
...
...
src/component/Product.jsx
View file @
4d719d79
import
React
from
'react'
import
'./../styles/Product.css'
import
React
,
{
useState
}
from
"react"
;
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
(
<
div
>
<
div
className=
"img-container"
>
<
img
src=
{
product
.
productImageUrl
}
alt=
{
product
.
productName
}
/>
</
div
>
<
div
className=
"prod-info"
>
<
h5
>
{
product
.
productName
}
</
h5
>
{
product
.
sku
}
<
br
/>
$
{
product
.
price
}
<
br
/>
In Stock:
{
product
.
stock
}
</
div
>
<
div
className=
"img-container"
onClick=
{
handleShow
}
>
<
img
className=
"grid-img"
src=
{
product
.
productImageUrl
}
alt=
{
product
.
productName
}
/>
</
div
>
<
div
className=
"prod-info"
>
<
h5
>
{
product
.
productName
}
</
h5
>
{
product
.
sku
}
<
br
/>
$
{
product
.
price
}
<
br
/>
In Stock:
{
product
.
stock
}
</
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
>
<
Button
variant=
"danger"
>
Yes, delete
</
Button
>
</
Alert
>
</
Modal
.
Footer
>
</
Modal
>
</
div
>
)
)
;
}
src/component/ProductForm.jsx
View file @
4d719d79
import
React
,
{
useState
}
from
"react"
;
import
{
useHistory
,
useLocation
}
from
"react-router"
;
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
{
useHistory
,
useParams
}
from
"react-router"
;
import
emptyProduct
from
"../emptProduct"
;
const
emptyForm
=
{
sku
:
""
,
upc
:
""
,
productName
:
""
,
brand
:
""
,
category
:
""
,
price
:
0.0
,
availableStock
:
0
,
productDescription
:
""
,
productImageUrl
:
""
,
productImage
:
""
...
emptyProduct
,
imageFile
:
""
,
};
ProductForm
.
defaultProps
=
{
...
...
@@ -19,15 +12,34 @@ ProductForm.defaultProps = {
};
export
default
function
ProductForm
(
props
)
{
const
{
product
}
=
props
;
const
[
form
,
setForm
]
=
useState
(
product
);
const
{
method
}
=
props
;
const
[
form
,
setForm
]
=
useState
({
...
emptyForm
});
const
[
imageMode
,
setImageMode
]
=
useState
(
"url"
);
const
[
errors
,
setErrors
]
=
useState
([]);
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
=
()
=>
{
setErrors
([]);
const
errs
=
[];
console
.
log
(
form
)
if
(
form
.
sku
.
length
<
3
)
{
errs
.
push
(
"SKU must be at least 3 characters"
);
}
...
...
@@ -56,11 +68,20 @@ export default function ProductForm(props) {
const
onSubmit
=
(
e
)
=>
{
e
.
preventDefault
();
validate
();
if
(
imageMode
===
"url"
)
{
delete
form
.
imageFile
;
}
else
{
delete
form
.
prodImgUrl
;
}
if
(
errors
.
length
===
0
)
{
// console.log(form);
fetch
(
"http://localhost:8080/api/products"
,
{
method
:
"POST"
,
const
url
=
method
===
"PUT"
?
`
${
Config
.
inventoryUrl
}
/
${
sku
}
`
:
`
${
Config
.
inventoryUrl
}
`
;
fetch
(
url
,
{
method
,
headers
:
{
"Content-Type"
:
"application/json"
,
},
...
...
@@ -100,11 +121,13 @@ export default function ProductForm(props) {
SKU
</
label
>
<
input
disabled=
{
method
===
"PUT"
?
true
:
false
}
required
name=
"sku"
type=
"text"
className=
"form-control"
id=
"productSku"
disabled=
{
method
===
"PUT"
?
true
:
false
}
value=
{
form
.
sku
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
sku
:
e
.
target
.
value
})
}
/>
...
...
@@ -137,7 +160,9 @@ export default function ProductForm(props) {
className=
"form-control"
id=
"productName"
value=
{
form
.
productName
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
productName
:
e
.
target
.
value
})
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
productName
:
e
.
target
.
value
})
}
/>
</
div
>
<
div
>
...
...
@@ -170,17 +195,19 @@ export default function ProductForm(props) {
</
div
>
</
div
>
<
div
className=
"col-6"
>
<
label
htmlFor=
"productDesc
ription
"
className=
"form-label"
>
<
label
htmlFor=
"productDesc"
className=
"form-label"
>
Description
</
label
>
<
textarea
name=
"productDesc
r
iption"
id=
"productDesc
ription
"
name=
"productDesciption"
id=
"productDesc"
cols=
"40"
rows=
"7"
className=
"form-control"
value=
{
form
.
productDescription
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
productDescription
:
e
.
target
.
value
})
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
productDescription
:
e
.
target
.
value
})
}
></
textarea
>
</
div
>
</
div
>
...
...
@@ -204,8 +231,9 @@ export default function ProductForm(props) {
Stock
</
label
>
<
input
disabled=
{
method
===
"PUT"
?
true
:
false
}
required
name=
"
s
tock"
name=
"
availableS
tock"
type=
"number"
className=
"form-control"
id=
"stock"
...
...
@@ -214,28 +242,61 @@ export default function ProductForm(props) {
/>
</
div
>
</
div
>
<
div
className=
"row mt-3"
>
<
label
htmlFor=
"productImage"
className=
"form-label"
>
Product Image
</
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
id=
"productImage"
name=
"productImage"
className=
"form-control form-control-lg"
type=
"file"
value=
{
form
.
productImage
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
productImage
:
e
.
target
.
value
,
productImageUrl
:
""
})
}
></
input
>
</
div
>
{
imageMode
===
"upload"
?
(
<
div
className=
"row mt-3"
>
<
div
>
<
label
htmlFor=
"productImage"
className=
"form-label"
>
Image File
</
label
>
<
input
id=
"productImage"
name=
"imageFile"
className=
"form-control form-control-lg"
type=
"file"
value=
{
form
.
imageFile
}
onChange=
{
(
e
)
=>
setForm
({
...
form
,
imageFile
:
e
.
target
.
value
})
}
></
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
>
)
:
null
}
<
div
className=
"row mt-3"
>
<
div
className=
"col-12"
>
...
...
src/component/ProductGrid.jsx
View file @
4d719d79
import
React
from
"react"
;
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
Product
from
"./Product.jsx"
;
import
{
Col
,
Container
,
Row
}
from
"react-bootstrap"
;
import
"./../styles/ProductGrid.css"
;
import
Config
from
"../config.js"
;
import
{
Link
}
from
"react-router-dom"
;
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
(
<
div
>
<
h1
id=
"title"
className=
"text-center"
>
Inventory
</
h1
>
<
Container
id=
"prod-grid"
className=
"mt-3"
>
<
div
class=
"container flex-column d-flex justify-content-center"
>
<
div
className=
"container mt-3 d-flex justify-content-between align-items-center"
>
<
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
}
>
{
product
Data
.
map
((
product
)
=>
{
{
product
s
.
map
((
product
)
=>
{
return
(
<
Col
key=
{
product
.
sku
}
>
<
Product
product=
{
product
}
/>
...
...
src/config.js
View file @
4d719d79
...
...
@@ -3,4 +3,4 @@ class Config {
static
promotionsUrl
=
"http://localhost:8081/api/promos"
;
}
export
default
Config
;
\ No newline at end of file
export
default
Config
;
src/emptProduct.js
0 → 100644
View file @
4d719d79
const
emptyProduct
=
{
sku
:
""
,
upc
:
""
,
productName
:
""
,
brand
:
""
,
category
:
""
,
price
:
0.0
,
availableStock
:
0
,
productDesciption
:
""
,
productImageUrl
:
""
,
};
export
default
emptyProduct
;
src/styles/Product.css
View file @
4d719d79
img
{
max-width
:
100%
;
max-height
:
250px
;
}
.img-container
{
position
:
relative
;
overflow
:
hidden
;
padding-bottom
:
100%
;
}
img
{
.grid-
img
{
position
:
absolute
;
max-width
:
100%
;
max-height
:
100%
;
top
:
50%
;
left
:
50%
;
transform
:
translateX
(
-50%
)
translateY
(
-50%
);
}
.modal-img
{
display
:
flex
;
justify-content
:
center
;
}
.alert
{
width
:
100%
;
}
\ No newline at end of file
yarn.lock
View file @
4d719d79
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment