Commit 838e5fb4 authored by Philippe Fonzin's avatar Philippe Fonzin

Merge branch 'fix/style' into 'master'

Fix/style

See merge request !22
parents 97c61015 b728ae5a
File deleted
......@@ -3,6 +3,7 @@ target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
.DS_Store
### STS ###
.apt_generated
......
......@@ -17,27 +17,42 @@
---
## Details
#### Schema
### Schemas
#### Warehouse Order
```
{
_id: String
orderId: String
status: String "unfulfilled" (default) > "fulfilled"/"cancelled"
orderObject?: (will have it on initial Kafka message, not sure if we need to store this)
id: String,
orderId: String,
status: String "RECEIVED" (default) > "FULFILLED"/"CANCELLED",
createdAt: Date,
modifiedAt: Date,
orderItems: List<Item>,
address: String,
}
```
#### Workflow
- Warehouse Management (WM) expects an Order object (?) from Order Management (OM) on order placement in Kafka.
- On receipt of an Order object, WM will create a warehouse order entry in database with a status of "unfulfilled."
#### Item
```
{
itemId: String,
itemName: String,
itemQuantity: int,
itemPrice: float,
itemSku: int,
}
```
### Workflow
- Warehouse Management (WM) expects an Order object from Order Management (OM) on order creation in Kafka.
- On receipt of an Order object, WM will create a warehouse order entry in database with a status of **"RECEIVED"**.
- In the WM UI, a warehouse manager will have the ability to fulfill or cancel unfulfilled orders.
- When an order is marked **"fulfilled"** or **"cancelled"**, a Kafka message will be sent to be consumed.
- When an order is marked **"FULFILLED"** or **"CANCELLED"**, a Kafka message will be sent to be consumed.
#### UI
- Login
- Order status update screen mark orders as fulfilled or cancelled
- Order search
- Order information page
### UI
- Login/Logout
- Order Status and Update orders as **"FULFILLED"** or **"CANCELLED"**
- Order Filter and Search
- Order Details
#### API Documentation
https://documenter.getpostman.com/view/7402212/TzRNGATe
......@@ -10,6 +10,8 @@
content="Web site created using create-react-app"
/>
<link rel="stylesheet" href="./stylesheets/master.css">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
<!--
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/
......
......@@ -49,11 +49,11 @@
}
.filter-all:hover {
background: #2b4162;
background: #00567D;
color: white;
}
.filter-all.selected {
background: #2b4162;
background: #00567D;
}
.filter-rec:hover {
background: #2292A4;
......@@ -90,20 +90,20 @@
cursor: pointer;
padding: 10px 0;
font-size: 16px;
font-family: "Times New Roman", Times, serif;
font-family: 'Lato', sans-serif;
}
.search > input {
padding: 10px;
font-size: 16px;
font-family: "Times New Roman", Times, serif;
font-family: 'Lato', sans-serif;
}
.search-btn:hover,
.collapse-btn:hover,
.expand-btn:hover {
color: white;
background: #2b4162;
background: #00567D;
}
.search-select-error,
......
......@@ -2,21 +2,90 @@
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
padding: 10px 20px;
height: 50px;
background: #2b4162;
color: #fff;;
background: #00567D;
color: #EBEBEB;
font-size: 28px;
font-weight: 700;
}
.nisum-logo {
margin-right: 10px;
width: 100px;
height: 50px;
}
.header-module {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.header > div {
display: flex;
align-items: center;
}
.header img {
.user {
cursor: pointer;
position: relative;
display: flex;
align-items: center;
font-size: 20px;
padding: 10px;
}
.user:hover {
color: #CCCDCF;
}
.user img {
margin-right: 10px;
width: 32px;
height: 32px;
width: 32px;
border-radius: 50%;
}
.dropdown {
cursor: auto;
width: 100%;
position: absolute;
display: flex;
flex-direction: column;
background: white;
color: black;
padding: 10px;
border-radius: 4px;;
border: 1px solid black;
font-size: 16px;
font-weight: 400;
top: 30px;
right: 10px;
}
.dropdown > * ~ * {
margin-top: 10px;
}
.dropdown > * {
padding: 5px 10px;
}
.dropdown > *:hover {
background: #e9ecef;
}
.logout {
cursor: pointer;
}
.logout-btn {
border: none;
}
\ No newline at end of file
......@@ -5,10 +5,15 @@
@import './order.css';
@import './session.css';
/* background: #2b4162; */
/* background: #00567D; */
/* background: #4daa57 */
/* background: #c1292e */
/* background: #2292A4; */
/* background: #f5f0f6; */
/* background: #acb0bd; */
body {
font-family: 'Lato', sans-serif;
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
.order-index > h1 {
padding: 10px 20px;
margin-bottom: 2px;
background: #2b4162;
background: #00567D;
color: white;
font-size: 24px;
font-weight: 700;
......
const Image = ({ src }) => (
<img src={src} alt=""/>
const Image = ({ className, src }) => (
<img className={className} src={src} alt=""/>
)
export default Image;
\ No newline at end of file
......@@ -10,7 +10,10 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => {
const [inputError, setInputError] = useState(false);
const [byError, setByError] = useState(false);
const searchOptions = ["Warehouse ID", "Order ID"];
const searchOptions = [
// "Warehouse ID",
"Order ID"
];
const search = () => {
setInputError(false);
......@@ -24,17 +27,13 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => {
setByError(true);
} else {
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;
orders.allIds.map(id => {
const order = orders.byId[id];
if (order.orderId.toLowerCase().includes(searchInput.toLowerCase())) {
searchResult.allIds.push(id);
searchResult.byId[id] = orders.byId[id];
}
})
if (searchBy.length) {
setOrdersToShow(searchResult);
}
......
import Logout from "../session/Logout"
const Dropdown = ({ }) => {
return (
<div className="dropdown">
<div>Profile</div>
<Logout />
</div>
)
}
export default Dropdown;
\ No newline at end of file
import { connect } from "react-redux";
import Image from "../atoms/Image";
import Logout from "../session/Logout";
import User from "./User";
const Header = ({ isLoggedIn, logout }) => {
const Header = ({ isLoggedIn, user, logout }) => {
return (
<div className="header">
<div>
<Image src="./logo.svg" />
<Image className="nisum-logo" src="./nisum.jpeg" />
</div>
{/* <div>Ascend</div> */}
<div className="header-module">
<div>Warehouse Management</div>
</div>
{isLoggedIn ? <Logout onClick={logout} /> : null}
<div>{isLoggedIn ? <User user={user.user} /> : null}</div>
</div>
);
};
const mapStateToProps = (state) => ({
isLoggedIn: state.session.isAuthenticated,
user: state.session.user,
});
const mapDispatchToProps = (dispatch) => ({});
......
import { useState } from "react";
import Image from "../atoms/Image";
import Dropdown from "./Dropdown";
const User = ({ user }) => {
const [showDropdown, setShowDropdown] = useState(false);
return (
<div className="user" onClick={() => setShowDropdown(!showDropdown)}>
<Image src={user.imageUrl} />
<div>{user.givenName}</div>
{showDropdown ? <Dropdown /> : null}
</div>
);
}
export default User;
\ No newline at end of file
......@@ -5,19 +5,21 @@ import Button from "../atoms/Button";
const OrderButtons = ({ order, editOrder }) => {
const FULFILLED = "FULFILLED";
const CANCELLED = "CANCELLED";
const handleUpdate = (action) => {
console.log(action);
if (action === "FULFILL") {
editOrder({ ...order, status: "FULFILLED" });
} else if (action === "CANCEL") {
editOrder({ ...order, status: "CANCELLED" });
if (action === FULFILLED) {
editOrder({ ...order, status: FULFILLED });
} else if (action === CANCELLED) {
editOrder({ ...order, status: CANCELLED });
}
};
return (
<div className="oii-buttons">
<Button className="fulfill-btn" onClick={() => handleUpdate("FULFILL")} text="Fulfill"/>
<Button className="cancel-btn" onClick={() => handleUpdate("CANCEL")} text="Cancel"/>
<Button className="fulfill-btn" onClick={() => handleUpdate(FULFILLED)} text="Fulfill"/>
<Button className="cancel-btn" onClick={() => handleUpdate(CANCELLED)} text="Cancel"/>
</div>
);
};
......
......@@ -50,7 +50,7 @@ const OrderDetails = ({ order, showDetails }) => {
))}
</tbody>
</table>
{`Warehouse Order #: ${order.id}`}
{/* {`Warehouse Order #: ${order.id}`} */}
</div>
</div>
);
......
......@@ -11,6 +11,7 @@ const OrderIndexItem = ({
setExpandAll,
}) => {
const { orderId, status } = order;
const idToShow = orderId.slice(-7).toUpperCase();
const [showDetails, setShowDetails] = useState(false);
......@@ -44,7 +45,7 @@ const OrderIndexItem = ({
className={`oii-drop ${showDetails ? "rotate" : ""}`}
onClick={handleDropDown}
/>
<div className="oii-num">{`Order #: ${orderId}`}</div>
<div className="oii-num">{`Order #: ${idToShow}`}</div>
</div>
{actions}
</div>
......
......@@ -11,11 +11,14 @@ const Logout = ({ logout }) => {
};
return (
<div>
<div className="logout">
{/* Logout */}
<GoogleLogout
clientId={clientId}
buttonText="Logout"
// buttonText="Logout"
className="logout-btn"
onLogoutSuccess={responseGoogle}
render={props => (<div onClick={props.onClick}>Logout</div>)}
/>
</div>
);
......
......@@ -17,12 +17,10 @@ const OrdersReducer = (oldState = initialState, action) => {
const orderState = {
byId: {},
allIds: [],
byOrderId: {},
};
action.orders.forEach( order => {
orderState.allIds.push(order.id);
orderState.byId[order.id] = order;
orderState.byOrderId[order.orderId] = order;
})
return orderState;
case UPDATE_ORDER:
......
......@@ -9,15 +9,14 @@ import lombok.ToString;
@ToString
public class Address {
public Address() {
}
private String street;
private String city;
private String state;
private String zip;
public Address() {
}
public Address(String street, String city, String state, String zip) {
this.street = street;
this.city = city;
......
......@@ -14,10 +14,13 @@ public class Item {
private String itemId;
private String itemName;
private int itemQuantity;
private double itemPrice;
private int itemSku;
private float itemPrice;
private String itemSku;
public Item(String itemId, String itemName, int itemQuantity, double itemPrice, int itemSku) {
public Item() {
}
public Item(String itemId, String itemName, int itemQuantity, float itemPrice, String itemSku) {
this.itemId = itemId;
this.itemName = itemName;
this.itemQuantity = itemQuantity;
......@@ -25,7 +28,4 @@ public class Item {
this.itemSku = itemSku;
}
public Item() {
}
}
......@@ -8,6 +8,7 @@ import org.springframework.data.annotation.Id;
@Setter
public class Session {
@Id
private String token;
private User user;
}
package com.ascendfinalproject.warehouse.models;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String email;
private String familyName;
private String givenName;
private String googleId;
private String imageUrl;
private String name;
public User() {
}
}
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