Commit db3b5c9d authored by Alex Pinto's avatar Alex Pinto

Merge branch 'feat/styling' into 'master'

Feat/styling

See merge request !8
parents 23cc8f3a 23dfc92f
No preview for this file type
{ {
"name": "warehouse", "name": "warehouse",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 2, "lockfileVersion": 1,
"requires": true, "requires": true,
<<<<<<< HEAD
=======
"packages": { "packages": {
"": { "": {
"name": "warehouse", "name": "warehouse",
...@@ -19868,6 +19870,7 @@ ...@@ -19868,6 +19870,7 @@
} }
} }
}, },
>>>>>>> master
"dependencies": { "dependencies": {
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.12.13", "version": "7.12.13",
...@@ -34035,21 +34038,6 @@ ...@@ -34035,21 +34038,6 @@
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
}, },
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"string-length": { "string-length": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
...@@ -34106,6 +34094,21 @@ ...@@ -34106,6 +34094,21 @@
"define-properties": "^1.1.3" "define-properties": "^1.1.3"
} }
}, },
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"stringify-object": { "stringify-object": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
...@@ -35948,14 +35951,6 @@ ...@@ -35948,14 +35951,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}, },
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"string-width": { "string-width": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
...@@ -35981,6 +35976,14 @@ ...@@ -35981,6 +35976,14 @@
} }
} }
}, },
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
frontend/public/favicon.ico

3.78 KB | W: | H:

frontend/public/favicon.ico

1.04 KB | W: | H:

frontend/public/favicon.ico
frontend/public/favicon.ico
frontend/public/favicon.ico
frontend/public/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
name="description" name="description"
content="Web site created using create-react-app" content="Web site created using create-react-app"
/> />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="stylesheet" href="./stylesheets/master.css">
<!-- <!--
manifest.json provides metadata used when your web app is installed on a manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>React App</title> <title>Ascend Warehouse</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
......
...@@ -6,16 +6,6 @@ ...@@ -6,16 +6,6 @@
"src": "favicon.ico", "src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16", "sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon" "type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
} }
], ],
"start_url": ".", "start_url": ".",
......
.filter-search {
/* width: 50%; */
display: flex;
align-items: center;
padding: 20px;
}
.filter-search .text {
font-size: 20px;
font-weight: 700;
}
.filter-search > * ~ * {
margin-left: 100px;
}
.filter {
display: flex;
align-items: center;
}
.filter > * ~ * {
margin-left: 10px;
}
.filter-btns {
display: flex;
justify-content: space-between;
align-items: center;
}
.filter-btns > * {
cursor: pointer;
display: flex;
padding: 10px 20px;
border-radius: 5px;
border: 1px solid black;
}
.filter-btns > * ~ * {
margin-left: 10px;
}
.selected {
color: white;
}
.filter-all:hover {
background: orange;
color: white;
}
.filter-all.selected {
background: orange;
}
.filter-rec:hover {
background: blue;
color: white;
}
.filter-rec.selected {
background: blue;
}
.filter-ful:hover {
background: green;
color: white;
}
.filter-ful.selected {
background: green;
}
.filter-can:hover {
background: red;
color: white;
}
.filter-can.selected {
background: red;
}
.search {
display: flex;
align-items: center;
}
.search > * ~ * {
margin-left: 10px;
}
.search > select {
cursor: pointer;
border: none;
font-size: 16px;
font-family: 'Times New Roman', Times, serif;
}
.search > input {
padding: 10px;
font-size: 16px;
font-family: 'Times New Roman', Times, serif;
}
.search-btn {
cursor: pointer;
display: flex;
padding: 10px 20px;
border-radius: 5px;
border: 1px solid black;
}
.search-btn:hover {
color:white;
background: gray;
}
\ No newline at end of file
.footer {
display: flex;
align-items: center;
height: 50px;
background: gray;
color: white;
}
\ No newline at end of file
.header {
display: flex;
align-items: center;
height: 50px;
background: gray;
color: white;
}
\ No newline at end of file
@import './reset.css';
@import './header.css';
@import './footer.css';
@import './filter.css';
@import './order.css';
\ No newline at end of file
.order-index {
padding: 0 20px 20px;
}
.order-index > h1 {
padding: 10px 20px;
margin-bottom: 2px;
background: blue;
color: white;
font-size: 20px;
}
.order-index .oii ~ .oii {
margin-top: 15px;
}
.oii {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 70px;
background: lightgray;
border-radius: 5px;
}
.oii-container {
width: 100%;
display: flex;
justify-content: space-between;
padding: 15px;
box-sizing: border-box;
}
.oii-left {
display: flex;
align-items: center;
}
.oii-drop {
transition: transform 1s;
cursor: pointer;
margin-right: 10px;
padding: 5px;
font-size: 20px;
background: white;
border-radius: 50%;
}
.oii-drop.rotate {
transition: transform 1s;
transform: rotate(90deg);
}
.oii-num {
display: flex;
align-items: center;
}
.oii-buttons, .oii-status {
display: flex;
justify-content: center;
align-items: center;
width: 180px;
}
.oii-buttons > div {
cursor: pointer;
display: flex;
align-items: center;
background: white;
border-radius: 5px;
padding: 10px 20px;
}
.oii-buttons > * ~ * {
margin-left: 10px;
}
.oii-status.fulfilled {
color: green;
}
.oii-status.cancelled {
color: red;
}
.fulfill-btn {
position: relative;
border: 1px solid green;
color: green;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4),
0 1px 1px rgba(0, 0, 0, 0.5);
}
.fulfill-btn:hover {
color: white;
background: green;
box-shadow: none;
}
.cancel-btn {
position: relative;
border: 1px solid red;
color: red;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4),
0 1px 1px rgba(0, 0, 0, 0.5);
}
.cancel-btn:hover {
color: white;
background: red;
}
.fulfill-btn:active, .cancel-btn:active {
top: 2px;
}
.order-details {
display: flex;
flex-direction: column;
/* min-height: 0px; */
max-height: 0px;
overflow: hidden;
transition: max-height 1s ease-out;
}
.order-details-container {
overflow: hidden;
padding: 0 50px 20px;
box-sizing: border-box;
}
.animate {
transition: max-height 1s ease-out;
max-height: 200px;
}
.item-detail ~ .item-detail {
margin-top: 10px;
}
\ No newline at end of file
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
\ No newline at end of file
import Login from "./components/session/Login"; import { useEffect, useState } from "react";
import Logout from "./components/session/Logout"; import { connect } from "react-redux";
import Header from "./components/header/Header"; import Header from "./components/header/Header";
import Footer from "./components/footer/Footer";
import OrderIndex from "./components/order/OrderIndex" import OrderIndex from "./components/order/OrderIndex"
import NoOrders from "./components/order/NoOrders";
import { fetchOrders } from "./actions/order_actions";
import FilterSearch from "./components/filter/FilterSearch";
const App = ({ orders, fetchOrders }) => {
const [ordersToShow, setOrdersToShow] = useState(orders);
const [fetchAttempted, setFetchAttempted] = useState(false);
useEffect(() => {
if (!fetchAttempted) {
setFetchAttempted(true);
fetchOrders();
}
setOrdersToShow(orders);
}, [orders, fetchOrders, fetchAttempted]);
const App = () => {
return ( return (
<div className="app"> <div className="app">
<Login />
<Logout />
<Header /> <Header />
<OrderIndex /> <FilterSearch orders={orders} setOrdersToShow={setOrdersToShow} />
<Footer /> {ordersToShow.allIds.length ?
<OrderIndex orders={ordersToShow} /> :
<NoOrders />
}
</div> </div>
); );
} }
export default App; const mapStateToProps = (state) => ({
orders: state.entities.orders,
});
const mapDispatchToProps = (dispatch) => ({
fetchOrders: () => dispatch(fetchOrders()),
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
import * as OrderAPIUtil from '../util/orders_api_util'; import * as OrderAPIUtil from '../util/orders_api_util';
export const RECEIVE_ORDERS = 'RECEIVE_ORDERS'; export const RECEIVE_ORDERS = 'RECEIVE_ORDERS';
export const RECEIVE_ORDER = 'RECEIVE_ORDER';
export const UPDATE_ORDER = 'UPDATE_ORDER'; export const UPDATE_ORDER = 'UPDATE_ORDER';
const receiveOrders = (orders) => ({ const receiveOrders = (orders) => ({
...@@ -9,11 +8,6 @@ const receiveOrders = (orders) => ({ ...@@ -9,11 +8,6 @@ const receiveOrders = (orders) => ({
orders, orders,
}) })
const receiveOrder = (order) => ({
type: RECEIVE_ORDER,
order,
})
const updateOrder = (order) => ({ const updateOrder = (order) => ({
type: UPDATE_ORDER, type: UPDATE_ORDER,
order, order,
...@@ -22,19 +16,14 @@ const updateOrder = (order) => ({ ...@@ -22,19 +16,14 @@ const updateOrder = (order) => ({
export const fetchOrders = () => (dispatch) => { export const fetchOrders = () => (dispatch) => {
OrderAPIUtil.getOrders() OrderAPIUtil.getOrders()
.then(res => { .then(res => {
dispatch(receiveOrders(res)) dispatch(receiveOrders(res.data))
}); });
} }
export const createOrder = (order) => (dispatch) =>
OrderAPIUtil.createOrder(order)
.then(res => {
dispatch(receiveOrder(res))
});
export const editOrder = (order) => (dispatch) => { export const editOrder = (order) => (dispatch) => {
OrderAPIUtil.editOrder(order) OrderAPIUtil.editOrder(order)
.then(res => { .then(res => {
dispatch(updateOrder(res)) debugger
dispatch(updateOrder(res.data))
}); });
} }
\ No newline at end of file
const Button = ({ className, onClick, text }) => (
<div className={className} onClick={onClick}>
{text}
</div>
)
export default Button;
\ No newline at end of file
const Error = ({ text }) => (
<div>
{text}
</div>
)
export default Error;
\ No newline at end of file
const Input = ({ className, type, placeholder, value, onChange, onKeyPress }) => (
<input
type={type || "text"}
className={className}
placeholder={placeholder}
value={value}
onChange={onChange}
onKeyPress={onKeyPress}
/>
);
export default Input;
const Select = ({ defaultVal, value, onChange, options }) => (
<select
value={value ? value : defaultVal}
onChange={onChange}
>
{defaultVal ? (
<option disabled>{defaultVal}</option>
) : null}
{options.map(option => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
)
export default Select;
\ No newline at end of file
import { useEffect, useState } from "react";
import Button from "../atoms/Button";
import Input from "../atoms/Input";
import Select from "../atoms/Select";
import Search from "./Search";
const FilterSearch = ({ orders, setOrdersToShow }) => {
const [all, setAll] = useState(false);
const [received, setReceived] = useState(false);
const [fulfilled, setFulfilled] = useState(false);
const [cancelled, setCancelled] = useState(false);
const RECEIVED = "RECEIVED";
const FULFILLED = "FULFILLED";
const CANCELLED = "CANCELLED";
const reset = () => {
setAll(true);
setReceived(false);
setFulfilled(false);
setCancelled(false);
};
const receive = () => {
setAll(false);
setReceived(!received);
if (received && !fulfilled && !cancelled) {
setAll(true);
}
};
const fulfill = () => {
setAll(false);
setFulfilled(!fulfilled);
if (!received && fulfilled && !cancelled) {
setAll(true);
}
};
const cancel = () => {
setAll(false);
setCancelled(!cancelled);
if (!received && !fulfilled && cancelled) {
setAll(true);
}
};
useEffect(() => {
if (all) {
setOrdersToShow(orders);
} else {
const newOrders = { allIds: [], byId: {} };
orders.allIds.forEach((wareId) => {
const order = orders.byId[wareId];
switch (order.status) {
case RECEIVED:
if (all || received) {
newOrders.allIds.push(wareId);
newOrders.byId[wareId] = order;
}
break;
case FULFILLED:
if (all || fulfilled) {
newOrders.allIds.push(wareId);
newOrders.byId[wareId] = order;
}
break;
case CANCELLED:
if (all || cancelled) {
newOrders.allIds.push(wareId);
newOrders.byId[wareId] = order;
}
break;
default:
break;
}
});
setOrdersToShow(newOrders);
}
}, [orders, setOrdersToShow, all, received, fulfilled, cancelled]);
if (!orders.allIds.length) return null;
return (
<div className="filter-search">
<div className="filter">
<div className="text">Filter:</div>
<div className="filter-btns">
<Button
className={`filter-all ${all ? "selected" : ""}`}
onClick={reset}
text="All"
/>
<Button
className={`filter-rec ${received ? "selected" : ""}`}
onClick={receive}
text="Received"
/>
<Button
className={`filter-ful ${fulfilled ? "selected" : ""}`}
onClick={fulfill}
text="Fulfilled"
/>
<Button
className={`filter-can ${cancelled ? "selected" : ""}`}
onClick={cancel}
text="Cancelled"
/>
</div>
</div>
<Search setOrdersToShow={setOrdersToShow} />
</div>
);
};;
export default FilterSearch;
import { useState } from "react";
import { connect } from "react-redux";
import Select from "../atoms/Select";
import Input from "../atoms/Input";
import Button from "../atoms/Button";
const Search = ({ orders, setOrdersToShow }) => {
const [searchInput, setSearchInput] = useState("");
const [searchBy, setSearchBy] = useState("");
const searchOptions = ["by Warehouse ID", "by Order ID"];
const search = () => {
const searchResult = { allIds: [], byId: {} };
const searchedOrder =
searchBy === searchOptions[0]
? orders.byId[searchInput]
: searchBy === searchOptions[1]
? orders.byOrderId[searchInput]
: null;
if (searchedOrder) {
searchResult.allIds.push(searchedOrder.id);
searchResult.byId[searchedOrder.id] = searchedOrder;
}
if (searchBy.length) {
setOrdersToShow(searchResult);
}
setSearchInput("");
};
const handleSearchEnter = (e) => {
if (e.key === "Enter") {
search();
}
};
return (
<div className="search">
<div className="text">Search</div>
<Select
defaultVal={"By:"}
value={searchBy}
options={searchOptions}
onChange={(e) => {
setSearchBy(e.target.selectedOptions[0].value);
}}
/>
<Input
placeholder={"Search by ID"}
value={searchInput}
onChange={(e) => setSearchInput(e.target.value)}
onKeyPress={handleSearchEnter}
/>
<Button className="search-btn" text="Search" onClick={search} />
</div>
);
};
const mapStateToProps = (state) => ({
orders: state.entities.orders,
});
const mapDispatchToProps = (dispatch) => ({
});
export default connect(mapStateToProps, mapDispatchToProps)(Search);
import React from "react"; import React from "react";
const Footer = () => { const Footer = () => {
return <div>Footer</div>; return (
<div className="footer">
Footer
</div>
);
}; };
export default Footer; export default Footer;
import React from 'react'; import React from 'react';
import Login from "../session/Login";
import Logout from "../session/Logout";
const Header = () => { const Header = () => {
return ( return (
<div> <div className="header">
Header Warehouse Management
<Login />
<Logout />
</div> </div>
) );
} }
export default Header; export default Header;
\ No newline at end of file
const ItemDetails = ({ item }) => {
const { itemId, itemName, itemQuantity, itemPrice, itemSku } = item;
return (
<li className="item-detail">
{`${itemName} -- x ${itemQuantity} bought at ${itemPrice}/ea.`}
</li>
)
}
export default ItemDetails;
\ No newline at end of file
const NoOrders = () => (
<div>
No Orders To Show
</div>
)
export default NoOrders;
\ No newline at end of file
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { editOrder } from "../../actions/order_actions"; import { editOrder } from "../../actions/order_actions";
import Button from "../atoms/Button";
const OrderButtons = ({ order, editOrder }) => { const OrderButtons = ({ order, editOrder }) => {
// const { id, orderId, status, orderItems, createdAt, modifiedAt } = order;
const handleUpdate = (action) => { const handleUpdate = (action) => {
console.log(action); console.log(action);
if (action === "FULFILL") { if (action === "FULFILL") {
editOrder({ ...order, status: "FULFILLED"}) editOrder({ ...order, status: "FULFILLED" });
} else if (action === "CANCEL") { } else if (action === "CANCEL") {
editOrder({ ...order, status: "CANCELLED" }); editOrder({ ...order, status: "CANCELLED" });
} }
} };
const fulfill = (
<button onClick={() => handleUpdate("FULFILL")}>Fulfill</button>
)
const cancel = (
<button onClick={() => handleUpdate("CANCEL")}>Cancel</button>
)
return ( return (
<div> <div className="oii-buttons">
{fulfill} {cancel} <Button className="fulfill-btn" onClick={() => handleUpdate("FULFILL")} text="Fulfill"/>
<Button className="cancel-btn" onClick={() => handleUpdate("CANCEL")} text="Cancel"/>
</div> </div>
); );
}; };
......
import ItemDetails from "./ItemDetails";
const OrderDetails = ({ order, showDetails }) => {
return (
<div className={`order-details ${showDetails ? "animate" : ""}`}>
<div className="order-details-container">
<div>
{`Order Details - Warehouse Order #: ${order.id}`}
</div>
<ul>
{order.orderItems.map( item => (
<ItemDetails key={item.itemId}item={item} />
))}
</ul>
</div>
</div>
)
}
export default OrderDetails;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import OrderIndexItem from './OrderIndexItem'; import OrderIndexItem from './OrderIndexItem';
import { connect } from "react-redux";
import { createOrder, fetchOrders, editOrder } from '../../actions/order_actions';
const OrderIndex = ({ const OrderIndex = ({
orders, orders,
fetchOrders,
createOrder,
editOrder,
}) => { }) => {
const [fetchAttempted, setFetchAttempted] = useState(false);
useEffect(() => {
if (!fetchAttempted) {
setFetchAttempted(true);
fetchOrders();
}
}, [fetchOrders, fetchAttempted])
return ( return (
<div> <div className="order-index">
<h1>Order Index</h1> <h1>Order Index</h1>
<button onClick={createOrder}>Create New Order</button>
<button onClick={editOrder}>Update Order</button>
<br />
<br />
{orders.allIds.map((orderId) => { {orders.allIds.map((orderId) => {
const order = orders.byId[orderId]; const order = orders.byId[orderId];
return <OrderIndexItem key={order.id} order={order} />; return <OrderIndexItem key={order.id} order={order} />;
...@@ -36,14 +15,4 @@ const OrderIndex = ({ ...@@ -36,14 +15,4 @@ const OrderIndex = ({
} }
const mapStateToProps = (state) => ({ export default OrderIndex;
orders: state.entities.orders, \ No newline at end of file
})
const mapDispatchToProps = dispatch => ({
fetchOrders: () => dispatch(fetchOrders()),
createOrder: order => dispatch(createOrder(order)),
editOrder: order => dispatch(editOrder(order)),
})
export default connect(mapStateToProps, mapDispatchToProps)(OrderIndex)
import React from 'react'; import React, { useState } from 'react';
import OrderButtons from './OrderButtons'; import OrderButtons from './OrderButtons';
import { FiChevronRight } from 'react-icons/fi';
import OrderDetails from './OrderDetails';
const OrderIndexItem = ({ order }) => { const OrderIndexItem = ({ order }) => {
...@@ -12,16 +14,24 @@ const OrderIndexItem = ({ order }) => { ...@@ -12,16 +14,24 @@ const OrderIndexItem = ({ order }) => {
modifiedAt modifiedAt
} = order; } = order;
const actions = ( status === "RECEIVED" ? const [showDetails, setShowDetails] = useState(false);
const actions = ( status === "FULFILLED" || status === "CANCELLED" ?
<div className={`oii-status ${status.toLowerCase()}`}>{status}</div> :
<OrderButtons order={order} /> <OrderButtons order={order} />
: );
<div>{status}</div>)
return ( return (
<div> <div className="oii">
<div>{`Order #: ${orderId}`}</div> <div className="oii-container">
<div className="oii-left">
<FiChevronRight className={`oii-drop ${showDetails ? "rotate" : ""}`} onClick={() => setShowDetails(!showDetails)}/>
<div className="oii-num">{`Order #:${orderId}`}</div>
</div>
{actions} {actions}
</div>
<OrderDetails showDetails={showDetails} order={order} />
</div> </div>
) )
}; };
......
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; import App from './App';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import configureStore from './store/store'; import configureStore from './store/store';
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
\ No newline at end of file
import { import {
RECEIVE_ORDER,
RECEIVE_ORDERS, RECEIVE_ORDERS,
UPDATE_ORDER, UPDATE_ORDER,
} from "../../actions/order_actions"; } from "../../actions/order_actions";
...@@ -13,22 +12,19 @@ const OrdersReducer = (oldState = initialState, action) => { ...@@ -13,22 +12,19 @@ const OrdersReducer = (oldState = initialState, action) => {
Object.freeze(oldState); Object.freeze(oldState);
const newState = { ...oldState }; const newState = { ...oldState };
const order = action.order || null; const order = action.order || null;
switch (action.type) { switch (action.type) {
case RECEIVE_ORDERS: case RECEIVE_ORDERS:
const orderState = { const orderState = {
byId: {}, byId: {},
allIds: [], allIds: [],
byOrderId: {},
}; };
Object.keys(action.orders).forEach( wareId => { action.orders.forEach( order => {
orderState.allIds.push(wareId); orderState.allIds.push(order.id);
orderState.byId[wareId] = action.orders[wareId]; orderState.byId[order.id] = order;
orderState.byOrderId[order.orderId] = order;
}) })
return orderState; return orderState;
case RECEIVE_ORDER:
newState.byId[order.id] = order;
newState.allIds.push(order.id);
return newState;
case UPDATE_ORDER: case UPDATE_ORDER:
newState.byId[order.id] = order; newState.byId[order.id] = order;
return newState; return newState;
......
// import axios from 'axios'; import axios from 'axios';
const RECEIVED = "RECEIVED"; export const getOrders =() => {
// const FULFILLED = "FULFILLED"; return axios.get(`http://localhost:8080/api/orders`);
// const CANCELLED = "CANCELLED";
const sampleGetAll = {
// allIds: ["1", "2", "3"],
// byId: {
1: {
id: "1",
orderId: "o1",
status: RECEIVED,
orderItems: [
{
itemId: "17",
itemName: "Item 1",
itemQuantity: 4,
itemPrice: 17.99,
itemSku: 8765309,
},
{
itemId: "18",
itemName: "Item 2",
itemQuantity: 42,
itemPrice: 17.99,
itemSku: 8715309,
},
],
},
2: {
id: "2",
orderId: "o2",
status: RECEIVED,
orderItems: [
{
itemId: "17",
itemName: "Item 1",
itemQuantity: 3,
itemPrice: 17.99,
itemSku: 8765309,
},
{
itemId: "18",
itemName: "Item 2",
itemQuantity: 41,
itemPrice: 17.99,
itemSku: 8715309,
},
],
},
3: {
id: "3",
orderId: "o3",
status: RECEIVED,
orderItems: [
{
itemId: "17",
itemName: "Item 1",
itemQuantity: 2,
itemPrice: 17.99,
itemSku: 8765309,
},
{
itemId: "18",
itemName: "Item 2",
itemQuantity: 40,
itemPrice: 17.99,
itemSku: 8715309,
},
],
},
// },
};
const sampleNew = {
id: "4",
orderId: "o4",
status: RECEIVED,
};
const getAllPromise = new Promise( (resolve, reject) => {
resolve(sampleGetAll)
})
const createNewPromise = new Promise( (resolve, reject) => {
resolve(sampleNew)
})
export const getOrders = () => {
return getAllPromise;
};
export const createOrder = (order) => {
return createNewPromise;
} }
export const editOrder = (order) => { export const editOrder = (order) => {
return new Promise( (resolve, reject) => { debugger;
resolve(order); return axios.put(`http://localhost:8080/api/orders/${order.id}`, order)
})
} }
// export const getOrders =() => {
// return axios.get("http://localhost:8080/api/orders");
// }
\ No newline at end of file
...@@ -40,4 +40,17 @@ public class WarehouseController { ...@@ -40,4 +40,17 @@ public class WarehouseController {
return orderService.updateOrder(order, id); return orderService.updateOrder(order, id);
} }
@CrossOrigin
@DeleteMapping(value = "/orders/{id}")
public Mono<Void> deleteOrder(@PathVariable(value = "id") String id) {
return orderService.deleteOrder(id);
}
@CrossOrigin
@DeleteMapping(value = "/orders/all")
public Mono<Void> deleteAllOrders() {
System.out.println("Deleted all orders");
return orderService.deleteAllOrders();
}
} }
...@@ -50,4 +50,13 @@ public class WarehouseOrderService { ...@@ -50,4 +50,13 @@ public class WarehouseOrderService {
} }
public Mono<Void> deleteOrder(String id) {
return orderRepository.deleteById(id);
}
public Mono<Void> deleteAllOrders() {
return orderRepository.deleteAll();
}
} }
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