Commit 34d11898 authored by Alex Pinto's avatar Alex Pinto

fixed merge conflict

parents 49019ac4 ae3c1e20
.filter-search { .filter-search {
/* width: 50%; */
display: flex; display: flex;
align-items: center; align-items: center;
padding: 20px; padding: 20px;
...@@ -11,7 +10,7 @@ ...@@ -11,7 +10,7 @@
} }
.filter-search > * ~ * { .filter-search > * ~ * {
margin-left: 100px; margin-left: 50px;
} }
.filter { .filter {
...@@ -29,9 +28,13 @@ ...@@ -29,9 +28,13 @@
align-items: center; align-items: center;
} }
.filter-btns > * { .filter-btns > *,
.search-btn,
.collapse-btn,
.expand-btn {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
align-items: center;
padding: 10px 20px; padding: 10px 20px;
border-radius: 5px; border-radius: 5px;
border: 1px solid black; border: 1px solid black;
...@@ -46,32 +49,32 @@ ...@@ -46,32 +49,32 @@
} }
.filter-all:hover { .filter-all:hover {
background: orange; background: #2b4162;
color: white; color: white;
} }
.filter-all.selected { .filter-all.selected {
background: orange; background: #2b4162;
} }
.filter-rec:hover { .filter-rec:hover {
background: blue; background: #2292A4;
color: white; color: white;
} }
.filter-rec.selected { .filter-rec.selected {
background: blue; background: #2292A4;
} }
.filter-ful:hover { .filter-ful:hover {
background: green; background: #4daa57;
color: white; color: white;
} }
.filter-ful.selected { .filter-ful.selected {
background: green; background: #4daa57;
} }
.filter-can:hover { .filter-can:hover {
background: red; background: #c1292e;
color: white; color: white;
} }
.filter-can.selected { .filter-can.selected {
background: red; background: #c1292e;
} }
.search { .search {
...@@ -85,30 +88,39 @@ ...@@ -85,30 +88,39 @@
.search > select { .search > select {
cursor: pointer; cursor: pointer;
border: none; padding: 10px 0;
font-size: 16px; font-size: 16px;
font-family: 'Times New Roman', Times, serif; font-family: "Times New Roman", Times, serif;
} }
.search > input { .search > input {
padding: 10px; padding: 10px;
font-size: 16px; font-size: 16px;
font-family: 'Times New Roman', Times, serif; font-family: "Times New Roman", Times, serif;
} }
.search-btn { .search-btn:hover,
cursor: pointer; .collapse-btn:hover,
.expand-btn:hover {
color: white;
background: #2b4162;
}
.search-select-error,
.search-input-error {
border: 2px solid #c1292e;
}
.fs-collapse {
display: flex; display: flex;
padding: 10px 20px; justify-content: space-between;
border-radius: 5px;
border: 1px solid black;
} }
.search-btn:hover { .collapse-expand {
color:white; display: flex;
background: gray; padding: 20px;
} }
.error { .collapse-expand > * ~ * {
color: red; margin-left: 10px;
} }
\ No newline at end of file
.header { .header {
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
padding: 10px 20px;
height: 50px; height: 50px;
background: gray; background: #2b4162;
color: white; color: #fff;;
font-size: 28px;
font-weight: 700;
}
.header > div {
display: flex;
align-items: center;
}
.header img {
margin-right: 10px;
width: 32px;
height: 32px;
} }
\ No newline at end of file
...@@ -2,4 +2,13 @@ ...@@ -2,4 +2,13 @@
@import './header.css'; @import './header.css';
@import './footer.css'; @import './footer.css';
@import './filter.css'; @import './filter.css';
@import './order.css'; @import './order.css';
\ No newline at end of file @import './session.css';
/* background: #2b4162; */
/* background: #4daa57 */
/* background: #c1292e */
/* background: #2292A4; */
/* background: #f5f0f6; */
/* background: #acb0bd; */
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
.order-index > h1 { .order-index > h1 {
padding: 10px 20px; padding: 10px 20px;
margin-bottom: 2px; margin-bottom: 2px;
background: blue; background: #2b4162;
color: white; color: white;
font-size: 20px; font-size: 24px;
font-weight: 700;
} }
.order-index .oii ~ .oii { .order-index .oii ~ .oii {
margin-top: 15px; margin-top: 15px;
...@@ -17,8 +18,9 @@ ...@@ -17,8 +18,9 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
min-height: 70px; min-height: 70px;
background: lightgray; background: #eee;
border-radius: 5px; border-radius: 5px;
font-size: 24px;
} }
.oii-container { .oii-container {
...@@ -58,7 +60,8 @@ ...@@ -58,7 +60,8 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 180px; width: 200px;
font-size: 20px;
} }
.oii-buttons > div { .oii-buttons > div {
...@@ -75,37 +78,37 @@ ...@@ -75,37 +78,37 @@
} }
.oii-status.fulfilled { .oii-status.fulfilled {
color: green; color: #4daa57;
} }
.oii-status.cancelled { .oii-status.cancelled {
color: red; color: #c1292e;
} }
.fulfill-btn { .fulfill-btn {
position: relative; position: relative;
border: 1px solid green; border: 1px solid #4daa57;
color: green; color: #4daa57;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4),
0 1px 1px rgba(0, 0, 0, 0.5); 0 1px 1px rgba(0, 0, 0, 0.5);
} }
.fulfill-btn:hover { .fulfill-btn:hover {
color: white; color: white;
background: green; background: #4daa57;
box-shadow: none; box-shadow: none;
} }
.cancel-btn { .cancel-btn {
position: relative; position: relative;
border: 1px solid red; border: 1px solid #c1292e;
color: red; color: #c1292e;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4),
0 1px 1px rgba(0, 0, 0, 0.5); 0 1px 1px rgba(0, 0, 0, 0.5);
} }
.cancel-btn:hover { .cancel-btn:hover {
color: white; color: white;
background: red; background: #c1292e;
} }
.fulfill-btn:active, .cancel-btn:active { .fulfill-btn:active, .cancel-btn:active {
...@@ -115,7 +118,7 @@ ...@@ -115,7 +118,7 @@
.order-details { .order-details {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
/* min-height: 0px; */ font-size: 18px;
max-height: 0px; max-height: 0px;
overflow: hidden; overflow: hidden;
transition: max-height 1s ease-out; transition: max-height 1s ease-out;
...@@ -123,15 +126,73 @@ ...@@ -123,15 +126,73 @@
.order-details-container { .order-details-container {
overflow: hidden; overflow: hidden;
padding: 0 50px 20px; padding: 20px 50px;
box-sizing: border-box; box-sizing: border-box;
overflow: scroll;
} }
.animate { .animate {
transition: max-height 1s ease-out; transition: max-height 0.75s ease-in-out;
max-height: 200px; max-height: 400px;
} }
.item-detail ~ .item-detail { .order-details-header {
margin-top: 10px; padding: 4px 0;
font-size: 20px;
font-weight: 700;
border-bottom: 2px solid black;
display: flex;
justify-content: space-between;
}
.order-details-name {
display: flex;
align-items: center;
}
.order-details-dates {
display: flex;
flex-direction: column;
font-weight: 400;
font-size: 16px;
font-style: italic;
width: 275px;
}
.order-details-dates > div {
display: flex;
justify-content: space-between;
}
.order-detail-table {
margin: 15px;
}
.order-detail-table thead {
font-weight: 700;
border-bottom: 1px solid black;
}
.order-detail-table th,
.order-detail-table td {
padding: 5px 20px;
}
.item-sku, .item-qty {
text-align: center;
}
.item-price {
text-align: end;
}
.order-detail-table th ~ th,
.order-detail-table td ~ td {
border-left: 1px solid black;
}
.no-orders {
padding: 50px;
display: flex;
justify-content: center;
font-size: 28px;
} }
\ No newline at end of file
...@@ -40,4 +40,7 @@ q:before, q:after { ...@@ -40,4 +40,7 @@ q:before, q:after {
table { table {
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;
}
select:focus, input:focus {
outline: none;
} }
\ No newline at end of file
.login {
padding: 50px;
display: flex;
justify-content: center;
}
\ No newline at end of file
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import Header from "./components/header/Header"; import OrderIndex from "./components/order/OrderIndex";
import OrderIndex from "./components/order/OrderIndex"
import NoOrders from "./components/order/NoOrders"; import NoOrders from "./components/order/NoOrders";
import { fetchOrders } from "./actions/order_actions"; import { fetchOrders } from "./actions/order_actions";
import FilterSearch from "./components/filter/FilterSearch"; import FilterSearch from "./components/filter/FilterSearch";
import Button from "./components/atoms/Button";
const App = ({ orders, fetchOrders }) => { const App = ({ orders, fetchOrders }) => {
const [ordersToShow, setOrdersToShow] = useState(orders); const [ordersToShow, setOrdersToShow] = useState(orders);
const [fetchAttempted, setFetchAttempted] = useState(false); const [fetchAttempted, setFetchAttempted] = useState(false);
const [collapseAll, setCollapseAll] = useState(false);
// debugger const [expandAll, setExpandAll] = useState(false);
useEffect(() => { useEffect(() => {
if (!fetchAttempted) { if (!fetchAttempted) {
...@@ -23,16 +22,35 @@ const App = ({ orders, fetchOrders }) => { ...@@ -23,16 +22,35 @@ const App = ({ orders, fetchOrders }) => {
return ( return (
<div className="app"> <div className="app">
<Header /> <div className="fs-collapse">
<FilterSearch setOrdersToShow={setOrdersToShow} /> <FilterSearch setOrdersToShow={setOrdersToShow} />
<div className="collapse-expand">
<Button
className="collapse-btn"
onClick={() => setCollapseAll(true)}
text={`Collapse All`}
/>
<Button
className="expand-btn"
onClick={() => setExpandAll(true)}
text={`Expand All`}
/>
</div>
</div>
{ordersToShow.allIds.length ? ( {ordersToShow.allIds.length ? (
<OrderIndex orders={ordersToShow} /> <OrderIndex
orders={ordersToShow}
collapseAll={collapseAll}
expandAll={expandAll}
setCollapseAll={setCollapseAll}
setExpandAll={setExpandAll}
/>
) : ( ) : (
<NoOrders /> <NoOrders />
)} )}
</div> </div>
); );
} };
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
orders: state.entities.orders, orders: state.entities.orders,
......
import { connect } from "react-redux";
import Header from "./components/header/Header";
import App from "./App"
import Login from "./components/session/Login";
const Root = ({ isLoggedIn }) => {
return (
<div>
<Header />
{isLoggedIn ?
<App /> :
<Login />
}
</div>
);
}
const mapStateToProps = (state) => ({
isLoggedIn: state.session.isAuthenticated,
});
const mapDispatchToProps = (dispatch) => ({
});
export default connect(mapStateToProps, mapDispatchToProps)(Root);
\ No newline at end of file
...@@ -23,7 +23,6 @@ export const fetchOrders = () => (dispatch) => { ...@@ -23,7 +23,6 @@ export const fetchOrders = () => (dispatch) => {
export const editOrder = (order) => (dispatch) => { export const editOrder = (order) => (dispatch) => {
OrderAPIUtil.editOrder(order) OrderAPIUtil.editOrder(order)
.then(res => { .then(res => {
debugger
dispatch(updateOrder(res.data)) dispatch(updateOrder(res.data))
}); });
} }
\ No newline at end of file
import * as SessionAPIUtil from "../util/session_api_util";
export const LOGIN_USER = "LOGIN_USER";
export const LOGOUT_USER = "LOGOUT_USER";
const receiveLogin = (user) => ({
type: LOGIN_USER,
user,
});
const receiveLogout = () => ({
type: LOGOUT_USER,
});
export const login = (payload) => (dispatch) => {
SessionAPIUtil.createSession(payload).then((res) => {
const { status, data } = res;
if (status < 299) {
dispatch(receiveLogin(data));
}
});
};
export const logout = () => (dispatch) => {
dispatch(receiveLogout());
};
const Image = ({ src }) => (
<img src={src} alt=""/>
)
export default Image;
\ No newline at end of file
const Input = ({ className, type, placeholder, value, onChange, onKeyPress }) => ( const Input = ({
<input className,
type,
placeholder,
value,
onChange,
onBlur,
onKeyPress,
}) => (
<input
type={type || "text"} type={type || "text"}
className={className} className={className}
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}
onChange={onChange} onChange={onChange}
onBlur={onBlur}
onKeyPress={onKeyPress} onKeyPress={onKeyPress}
/> />
); );
......
const Select = ({ defaultVal, value, onChange, options }) => ( const Select = ({ className, defaultVal, value, onChange, options }) => (
<select <select
className={className}
value={value ? value : defaultVal} value={value ? value : defaultVal}
onChange={onChange} onChange={onChange}
> >
......
...@@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; ...@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import Button from "../atoms/Button"; import Button from "../atoms/Button";
const Filter = ({ orders, filtersOn, setOrdersToShow }) => { const Filter = ({ orders, filtersOn, setFiltersOn, setOrdersToShow }) => {
const [all, setAll] = useState(false); const [all, setAll] = useState(false);
const [received, setReceived] = useState(false); const [received, setReceived] = useState(false);
const [fulfilled, setFulfilled] = useState(false); const [fulfilled, setFulfilled] = useState(false);
...@@ -14,12 +14,14 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -14,12 +14,14 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
const reset = () => { const reset = () => {
setAll(true); setAll(true);
setFiltersOn(true);
setReceived(false); setReceived(false);
setFulfilled(false); setFulfilled(false);
setCancelled(false); setCancelled(false);
}; };
const receive = () => { const receive = () => {
setAll(false); setAll(false);
setFiltersOn(true);
setReceived(!received); setReceived(!received);
if (received && !fulfilled && !cancelled) { if (received && !fulfilled && !cancelled) {
setAll(true); setAll(true);
...@@ -27,6 +29,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -27,6 +29,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
}; };
const fulfill = () => { const fulfill = () => {
setAll(false); setAll(false);
setFiltersOn(true);
setFulfilled(!fulfilled); setFulfilled(!fulfilled);
if (!received && fulfilled && !cancelled) { if (!received && fulfilled && !cancelled) {
setAll(true); setAll(true);
...@@ -34,6 +37,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -34,6 +37,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
}; };
const cancel = () => { const cancel = () => {
setAll(false); setAll(false);
setFiltersOn(true);
setCancelled(!cancelled); setCancelled(!cancelled);
if (!received && !fulfilled && cancelled) { if (!received && !fulfilled && cancelled) {
setAll(true); setAll(true);
...@@ -41,7 +45,12 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -41,7 +45,12 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
}; };
useEffect(() => { useEffect(() => {
if (all || (!all && !received && !fulfilled && !cancelled)) { if (!filtersOn) {
setAll(false);
setReceived(false);
setFulfilled(false);
setCancelled(false);
} else if (all || (!all && !received && !fulfilled && !cancelled)) {
setOrdersToShow(orders); setOrdersToShow(orders);
} else { } else {
const newOrders = { allIds: [], byId: {} }; const newOrders = { allIds: [], byId: {} };
...@@ -72,7 +81,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -72,7 +81,7 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
}); });
setOrdersToShow(newOrders); setOrdersToShow(newOrders);
} }
}, [orders, setOrdersToShow, all, received, fulfilled, cancelled]); }, [orders, setOrdersToShow, filtersOn, all, received, fulfilled, cancelled]);
if (!orders.allIds.length) return null; if (!orders.allIds.length) return null;
...@@ -82,22 +91,22 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => { ...@@ -82,22 +91,22 @@ const Filter = ({ orders, filtersOn, setOrdersToShow }) => {
<div className="filter-btns"> <div className="filter-btns">
<Button <Button
className={`filter-all ${filtersOn && all ? "selected" : ""}`} className={`filter-all ${all ? "selected" : ""}`}
onClick={reset} onClick={reset}
text="All" text="All"
/> />
<Button <Button
className={`filter-rec ${filtersOn && received ? "selected" : ""}`} className={`filter-rec ${received ? "selected" : ""}`}
onClick={receive} onClick={receive}
text="Received" text="Received"
/> />
<Button <Button
className={`filter-ful ${filtersOn && fulfilled ? "selected" : ""}`} className={`filter-ful ${fulfilled ? "selected" : ""}`}
onClick={fulfill} onClick={fulfill}
text="Fulfilled" text="Fulfilled"
/> />
<Button <Button
className={`filter-can ${filtersOn && cancelled ? "selected" : ""}`} className={`filter-can ${cancelled ? "selected" : ""}`}
onClick={cancel} onClick={cancel}
text="Cancelled" text="Cancelled"
/> />
......
import { useEffect, useState } from "react"; import { useState } from "react";
import Filter from "./Filter"; import Filter from "./Filter";
import Search from "./Search"; import Search from "./Search";
const FilterSearch = ({ orders, setOrdersToShow }) => { const FilterSearch = ({ setOrdersToShow }) => {
const [filtersOn, setFiltersOn] = useState(true); const [filtersOn, setFiltersOn] = useState(true);
return ( return (
<div className="filter-search"> <div className="filter-search">
<Filter filtersOn={filtersOn} setOrdersToShow={setOrdersToShow} /> <Filter
<Search setOrdersToShow={setOrdersToShow} setFiltersOn={setFiltersOn}/> filtersOn={filtersOn}
setFiltersOn={setFiltersOn}
setOrdersToShow={setOrdersToShow}
/>
<Search setOrdersToShow={setOrdersToShow} setFiltersOn={setFiltersOn} />
</div> </div>
); );
}; };
......
...@@ -3,20 +3,25 @@ import { connect } from "react-redux"; ...@@ -3,20 +3,25 @@ import { connect } from "react-redux";
import Select from "../atoms/Select"; import Select from "../atoms/Select";
import Input from "../atoms/Input"; import Input from "../atoms/Input";
import Button from "../atoms/Button"; import Button from "../atoms/Button";
import Error from "../atoms/Error";
const Search = ({ orders, setOrdersToShow, setFiltersOn }) => { const Search = ({ orders, setOrdersToShow, setFiltersOn }) => {
const [searchInput, setSearchInput] = useState(""); const [searchInput, setSearchInput] = useState("");
const [searchBy, setSearchBy] = useState(""); const [searchBy, setSearchBy] = useState("");
const [error, setError] = useState(""); const [inputError, setInputError] = useState(false);
const [byError, setByError] = useState(false);
const searchOptions = ["by Warehouse ID", "by Order ID"]; const searchOptions = ["Warehouse ID", "Order ID"];
const search = () => { const search = () => {
if (!searchInput.length) { setInputError(false);
setError("Please enter a search parameter."); setByError(false);
if (!searchInput.length && !searchBy.length) {
setInputError(true);
setByError(true);
} else if (!searchInput.length) {
setInputError(true);
} else if (!searchBy.length) { } else if (!searchBy.length) {
setError("Please enter search method."); setByError(true);
} else { } else {
const searchResult = { allIds: [], byId: {} }; const searchResult = { allIds: [], byId: {} };
const searchedOrder = const searchedOrder =
...@@ -33,10 +38,15 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => { ...@@ -33,10 +38,15 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => {
if (searchBy.length) { if (searchBy.length) {
setOrdersToShow(searchResult); setOrdersToShow(searchResult);
} }
setError("");
setSearchInput(""); setSearchInput("");
setFiltersOn(false); setFiltersOn(false);
} }
};
const handleInputBlur = (e) => {
if (!e.target.value.length) {
setInputError(true);
}
}; };
const handleSearchEnter = (e) => { const handleSearchEnter = (e) => {
...@@ -47,23 +57,29 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => { ...@@ -47,23 +57,29 @@ const Search = ({ orders, setOrdersToShow, setFiltersOn }) => {
return ( return (
<div className="search"> <div className="search">
<div className="text">Search</div> <div className="text">Search:</div>
<Select <Select
defaultVal={"By:"} className={byError ? "search-select-error" : ""}
defaultVal={"Choose one.."}
value={searchBy} value={searchBy}
options={searchOptions} options={searchOptions}
onChange={(e) => { onChange={(e) => {
setByError(false);
setSearchBy(e.target.selectedOptions[0].value); setSearchBy(e.target.selectedOptions[0].value);
}} }}
/> />
<Input <Input
className={inputError ? "search-input-error" : ""}
placeholder={"Search by ID"} placeholder={"Search by ID"}
value={searchInput} value={searchInput}
onChange={(e) => setSearchInput(e.target.value)} onChange={(e) => {
setInputError(false);
setSearchInput(e.target.value);
}}
onBlur={handleInputBlur}
onKeyPress={handleSearchEnter} onKeyPress={handleSearchEnter}
/> />
<Button className="search-btn" text="Search" onClick={search} /> <Button className="search-btn" text="Search" onClick={search} />
{error.length ? <Error text={error}/> : null}
</div> </div>
); );
}; };
...@@ -72,7 +88,6 @@ const mapStateToProps = (state) => ({ ...@@ -72,7 +88,6 @@ const mapStateToProps = (state) => ({
orders: state.entities.orders, orders: state.entities.orders,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({});
});
export default connect(mapStateToProps, mapDispatchToProps)(Search); export default connect(mapStateToProps, mapDispatchToProps)(Search);
import React from 'react'; import { connect } from "react-redux";
import Login from "../session/Login"; import Image from "../atoms/Image";
import Logout from "../session/Logout"; import Logout from "../session/Logout";
const Header = () => { const Header = ({ isLoggedIn, logout }) => {
return ( return (
<div className="header"> <div className="header">
Warehouse Management <div>
<Login /> <Image src="https://www.flaticon.com/svg/vstatic/svg/2562/2562296.svg?token=exp=1620448865~hmac=b6bb0b0a072e16f423c481f7a3175fa9" />
<Logout /> <div>Warehouse Management</div>
</div>
{isLoggedIn ? <Logout onClick={logout} /> : null}
</div> </div>
); );
} };
export default Header; const mapStateToProps = (state) => ({
\ No newline at end of file isLoggedIn: state.session.isAuthenticated,
});
const mapDispatchToProps = (dispatch) => ({});
export default connect(mapStateToProps, mapDispatchToProps)(Header);
const ItemDetails = ({ item }) => { const ItemDetails = ({ item }) => {
const { itemName, itemQuantity, itemPrice, itemSku } = item;
const { itemId, itemName, itemQuantity, itemPrice, itemSku } = item;
return ( return (
<li className="item-detail"> <tr className="item-detail">
{`${itemName} -- x ${itemQuantity} bought at ${itemPrice}/ea.`} <td className="item-sku">{itemSku}</td>
</li> <td className="item-name">{itemName}</td>
) <td className="item-qty">{itemQuantity}</td>
} <td className="item-price">{`$${itemPrice.toFixed(2)}`}</td>
</tr>
);
};
export default ItemDetails; export default ItemDetails;
\ No newline at end of file
const NoOrders = () => ( const NoOrders = () => (
<div> <div className="no-orders">
No Orders To Show Hmm, it doesn't seem like there were any orders found...
</div> </div>
) )
export default NoOrders; export default NoOrders;
\ No newline at end of file
import ItemDetails from "./ItemDetails"; import ItemDetails from "./ItemDetails";
const OrderDetails = ({ order, showDetails }) => { const OrderDetails = ({ order, showDetails }) => {
const createdDate = new Date(order.createdAt);
const modifiedDate = new Date(order.modifiedAt);
const status =
order.status[0].toUpperCase() + order.status.substr(1).toLowerCase();
const dateToString = (date) => {
const month = date.toLocaleString("default", { month: "short" });
const day = date.getDate();
const year = date.getFullYear();
const hour = date.getHours();
const cHour = hour > 12 ? hour - 12 : hour;
const minute = date.getMinutes();
const time = `${cHour > 9 ? cHour : `0${cHour}`}:${minute > 9 ? minute : `0${minute}`}`;
return `${month} ${day > 9 ? day : `0${day}`}, ${year} at ${time} ${hour > 11 ? "PM" : "AM"}`;
};
return ( return (
<div className={`order-details ${showDetails ? "animate" : ""}`}> <div className={`order-details ${showDetails ? "animate" : ""}`}>
<div className="order-details-container"> <div className="order-details-container">
<div> <div className="order-details-header">
{`Order Details - Warehouse Order #: ${order.id}`} <div className="order-details-name">Order Details:</div>
<div className="order-details-dates">
<div>
<div>Created on:</div>
<div>{dateToString(createdDate)}</div>
</div>
{order.modifiedAt ? (
<div>
<div>{`${status} on:`}</div>
<div>{dateToString(modifiedDate)}</div>
</div>
) : null}
</div>
</div> </div>
<ul> <table className="order-detail-table">
{order.orderItems.map( item => ( <thead>
<ItemDetails key={item.itemId}item={item} /> <tr>
))} <th>SKU #</th>
</ul> <th>Name</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{order.orderItems.map((item) => (
<ItemDetails key={item.itemId} item={item} />
))}
</tbody>
</table>
{`Warehouse Order #: ${order.id}`}
</div> </div>
</div> </div>
) );
} };
export default OrderDetails; export default OrderDetails;
\ No newline at end of file
...@@ -2,13 +2,26 @@ import OrderIndexItem from './OrderIndexItem'; ...@@ -2,13 +2,26 @@ import OrderIndexItem from './OrderIndexItem';
const OrderIndex = ({ const OrderIndex = ({
orders, orders,
collapseAll,
expandAll,
setCollapseAll,
setExpandAll,
}) => { }) => {
return ( return (
<div className="order-index"> <div className="order-index">
<h1>Order Index</h1> <h1>Orders</h1>
{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}
collapseAll={collapseAll}
expandAll={expandAll}
setCollapseAll={setCollapseAll}
setExpandAll={setExpandAll}
/>
);
})} })}
</div> </div>
); );
......
import React, { useState } from 'react'; import React, { useEffect, useState } from "react";
import OrderButtons from './OrderButtons'; import OrderButtons from "./OrderButtons";
import { FiChevronRight } from 'react-icons/fi'; import { FiChevronRight } from "react-icons/fi";
import OrderDetails from './OrderDetails'; import OrderDetails from "./OrderDetails";
const OrderIndexItem = ({ order }) => { const OrderIndexItem = ({
order,
const { collapseAll,
id, expandAll,
orderId, setCollapseAll,
status, setExpandAll,
orderItems, }) => {
createdAt, const { orderId, status } = order;
modifiedAt
} = order;
const [showDetails, setShowDetails] = useState(false); const [showDetails, setShowDetails] = useState(false);
const actions = ( status === "FULFILLED" || status === "CANCELLED" ? useEffect(() => {
<div className={`oii-status ${status.toLowerCase()}`}>{status}</div> : if (collapseAll) {
<OrderButtons order={order} /> setShowDetails(false);
); }
if (expandAll) {
setShowDetails(true);
}
setCollapseAll(false);
setExpandAll(false);
}, [showDetails, collapseAll, expandAll, setCollapseAll, setExpandAll]);
const handleDropDown = () => {
setShowDetails(!showDetails);
};
const actions =
status === "FULFILLED" || status === "CANCELLED" ? (
<div className={`oii-status ${status.toLowerCase()}`}>{status}</div>
) : (
<OrderButtons order={order} />
);
return ( return (
<div className="oii"> <div className="oii">
<div className="oii-container"> <div className="oii-container">
<div className="oii-left"> <div className="oii-left">
<FiChevronRight className={`oii-drop ${showDetails ? "rotate" : ""}`} onClick={() => setShowDetails(!showDetails)}/> <FiChevronRight
className={`oii-drop ${showDetails ? "rotate" : ""}`}
onClick={handleDropDown}
/>
<div className="oii-num">{`Order #: ${orderId}`}</div> <div className="oii-num">{`Order #: ${orderId}`}</div>
</div> </div>
{actions} {actions}
...@@ -33,7 +51,7 @@ const OrderIndexItem = ({ order }) => { ...@@ -33,7 +51,7 @@ const OrderIndexItem = ({ order }) => {
<OrderDetails showDetails={showDetails} order={order} /> <OrderDetails showDetails={showDetails} order={order} />
</div> </div>
) );
}; };
export default OrderIndexItem; export default OrderIndexItem;
import React from 'react'; import React from "react";
import { connect } from "react-redux";
import { GoogleLogin } from "react-google-login"; import { GoogleLogin } from "react-google-login";
import keys from "../../config/keys_dev" import keys from "../../config/keys_dev";
import { login } from "../../actions/session_actions";
const clientId = keys.clientId; const clientId = keys.clientId;
const Login = () => { const Login = ({ login }) => {
const responseGoogle = (googleResponse) => {
const responseGoogle = (response) => { const { tokenId, profileObj } = googleResponse;
console.log(response); login({ token: tokenId, user: profileObj });
}; };
return ( return (
<div> <div className="login">
<GoogleLogin <GoogleLogin
clientId={clientId} clientId={clientId}
buttonText="Login with Google" buttonText="Login with Google"
onSuccess={responseGoogle} onSuccess={responseGoogle}
onFailure={responseGoogle} onFailure={responseGoogle}
cookiePolicy={"single_host_origin"} cookiePolicy={"single_host_origin"}
// isSignedIn={true} isSignedIn={true}
/> />
</div> </div>
); );
} };
const mapStateToProps = (state) => ({});
const mapDispatchToProps = (dispatch) => ({
login: (token) => dispatch(login(token)),
});
export default Login; export default connect(mapStateToProps, mapDispatchToProps)(Login);
\ No newline at end of file
import React from "react"; import { connect } from "react-redux";
import { GoogleLogout } from "react-google-login"; import { GoogleLogout } from "react-google-login";
import { logout } from "../../actions/session_actions";
import keys from "../../config/keys_dev"; import keys from "../../config/keys_dev";
const clientId = keys.clientId; const clientId = keys.clientId;
const Logout = () => { const Logout = ({ logout }) => {
const responseGoogle = (googleResponse) => {
const responseGoogle = (response) => { logout();
console.log(response);
}; };
return ( return (
<div> <div>
<GoogleLogout <GoogleLogout
clientId={clientId} clientId={clientId}
buttonText="Logout" buttonText="Logout"
onLogoutSuccess={responseGoogle} onLogoutSuccess={responseGoogle}
isSignedIn={true}
/> />
</div> </div>
); );
}; };
export default Logout; const mapStateToProps = (state) => ({});
const mapDispatchToProps = (dispatch) => ({
logout: () => dispatch(logout()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Logout);
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import configureStore from './store/store'; import configureStore from './store/store';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import Root from './Root';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
...@@ -11,7 +11,7 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -11,7 +11,7 @@ document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render( ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<App /> <Root />
</Provider>, </Provider>,
document.getElementById('root') document.getElementById('root')
); );
......
import { combineReducers } from "redux"; import { combineReducers } from "redux";
import entities from "./entities/entities_reducer"; import entities from "./entities/entities_reducer";
import session from "./session/session_reducer";
const RootReducer = combineReducers({ const RootReducer = combineReducers({
entities, entities,
session,
}); });
export default RootReducer; export default RootReducer;
import { LOGIN_USER, LOGOUT_USER } from "../../actions/session_actions";
const initialState = {
isAuthenticated: false,
user: null
}
const SessionState = (oldState = initialState, action) => {
Object.freeze(oldState);
switch (action.type) {
case LOGIN_USER:
return {
isAuthenticated: !!action.user,
user: action.user,
}
case LOGOUT_USER:
return initialState;
default:
return oldState;
}
}
export default SessionState;
\ No newline at end of file
...@@ -5,6 +5,5 @@ export const getOrders =() => { ...@@ -5,6 +5,5 @@ export const getOrders =() => {
} }
export const editOrder = (order) => { export const editOrder = (order) => {
debugger;
return axios.put(`http://localhost:8080/api/orders/${order.id}`, order) return axios.put(`http://localhost:8080/api/orders/${order.id}`, order)
} }
import axios from "axios";
export const createSession = (payload) => {
return axios
.post("http://localhost:8080/api/auth", payload)
.catch((err) => err.response);
};
...@@ -7,8 +7,8 @@ import org.springframework.http.ResponseEntity; ...@@ -7,8 +7,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping(value = "") @RequestMapping(value = "/api")
public class AuthenticationController { public class SessionController {
@Autowired @Autowired
SessionService sessionService; SessionService sessionService;
......
...@@ -7,6 +7,7 @@ import com.ascendfinalproject.warehouse.services.SessionService; ...@@ -7,6 +7,7 @@ import com.ascendfinalproject.warehouse.services.SessionService;
import com.ascendfinalproject.warehouse.services.WarehouseOrderService; import com.ascendfinalproject.warehouse.services.WarehouseOrderService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
......
...@@ -12,10 +12,10 @@ public class Item { ...@@ -12,10 +12,10 @@ public class Item {
private String itemId; private String itemId;
private String itemName; private String itemName;
private int itemQuantity; private int itemQuantity;
private int itemPrice; private double itemPrice;
private int itemSku; private int itemSku;
public Item(String itemId, String itemName, int itemQuantity, int itemPrice, int itemSku) { public Item(String itemId, String itemName, int itemQuantity, double itemPrice, int itemSku) {
this.itemId = itemId; this.itemId = itemId;
this.itemName = itemName; this.itemName = itemName;
this.itemQuantity = itemQuantity; this.itemQuantity = itemQuantity;
......
...@@ -3,20 +3,26 @@ package com.ascendfinalproject.warehouse.models; ...@@ -3,20 +3,26 @@ package com.ascendfinalproject.warehouse.models;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Getter @Getter
@Setter @Setter
public class OrderResponse { public class OrderResponse {
private List<String> allIds; private List<String> allIds = new ArrayList<>();
private HashMap<String, WarehouseOrder> byId; private Map<String, WarehouseOrder> byId = new HashMap<>();
public void appendId(String id) { public void appendId(String id) {
allIds.add(id); allIds.add(id);
} }
public void addOrder(WarehouseOrder order) {
byId.put(order.getId(), order);
}
@Override @Override
public String toString() { public String toString() {
return "OrderResponse{" + return "OrderResponse{" +
......
...@@ -7,6 +7,7 @@ import org.springframework.stereotype.Service; ...@@ -7,6 +7,7 @@ import org.springframework.stereotype.Service;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Scanner;
@Service @Service
public class SessionService { public class SessionService {
...@@ -29,7 +30,7 @@ public class SessionService { ...@@ -29,7 +30,7 @@ public class SessionService {
.body(session); .body(session);
} }
return ResponseEntity return ResponseEntity
.status(HttpStatus.BAD_REQUEST) .status(HttpStatus.UNAUTHORIZED)
.body(session); .body(session);
......
...@@ -2,6 +2,7 @@ package com.ascendfinalproject.warehouse.services; ...@@ -2,6 +2,7 @@ package com.ascendfinalproject.warehouse.services;
import com.ascendfinalproject.warehouse.exceptions.NotFoundException; import com.ascendfinalproject.warehouse.exceptions.NotFoundException;
import com.ascendfinalproject.warehouse.models.Item; import com.ascendfinalproject.warehouse.models.Item;
import com.ascendfinalproject.warehouse.models.OrderResponse;
import com.ascendfinalproject.warehouse.models.WarehouseOrder; import com.ascendfinalproject.warehouse.models.WarehouseOrder;
import com.ascendfinalproject.warehouse.repositories.WarehouseOrderRepository; import com.ascendfinalproject.warehouse.repositories.WarehouseOrderRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -28,13 +29,12 @@ public class WarehouseOrderService { ...@@ -28,13 +29,12 @@ public class WarehouseOrderService {
} }
public Flux<WarehouseOrder> getOrders() { public Flux<WarehouseOrder> getOrders() {
return orderRepository.findAll(); return orderRepository.findAll();
} }
public Mono<WarehouseOrder> createOrder(WarehouseOrder order) { public Mono<WarehouseOrder> createOrder(WarehouseOrder order) {
order.setStatus("RECEIVED"); order.setStatus("RECEIVED");
order.setCreatedAt(new Date(System.currentTimeMillis())); order.setCreatedAt(new Date(System.currentTimeMillis()));
order.setModifiedAt(new Date(System.currentTimeMillis()));
List<Item> itemList = Arrays.asList( List<Item> itemList = Arrays.asList(
new Item("3", "Hamburger", 3, 3, 33), new Item("3", "Hamburger", 3, 3, 33),
new Item("4", "Sausage", 4, 5, 66), new Item("4", "Sausage", 4, 5, 66),
......
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