Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import RefreshIcon from "@material-ui/icons/Refresh";
import { useDispatch, useSelector } from "react-redux";
import styles from "pages/Orders/Orders.module.scss";
import {
adminOrderTotalSelector,
adminOrderTotalWithFiltersSelector,
getOrdersWithFilters,
} from "slices/order/adminOrderSlice";

Expand All @@ -13,7 +13,7 @@ const OrdersCount = () => {
const refreshOrders = () => {
dispatch(getOrdersWithFilters());
};
const orderQuantity = useSelector(adminOrderTotalSelector);
const orderQuantity = useSelector(adminOrderTotalWithFiltersSelector);
return (
<div className={styles.ordersBodyToolbarRefresh}>
<Typography variant="body2">{orderQuantity} results</Typography>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
}

.title {
margin-top: 20px;
text-justify: left;
margin-bottom: 10px;
margin-bottom: 5px;
font-family: "Roboto";
font-style: normal;
font-weight: 500;
Expand All @@ -22,3 +23,14 @@
.section {
margin-bottom: 1rem;
}

.overviewTitle {
padding-bottom: 10px;
}

.itemContent {
padding-left: 7px;
padding-bottom: 10px;
padding-top: 10px;
color: black;
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,145 @@
import React from "react";
import React, { useEffect } from "react";
import Typography from "@material-ui/core/Typography";
import Header from "components/general/Header/Header";
import { hackathonName } from "constants.js";
import OrderCard from "components/orders/OrderCard/OrderCard";
import { useDispatch, useSelector } from "react-redux";
import styles from "./AdminDashboard.module.scss";
import { hackathonName } from "constants.js";
import { OrderFilters } from "api/types";
import Box from "@material-ui/core/Box";
import Grid from "@material-ui/core/Grid";
import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";
import { styled } from "@material-ui/core/styles";
import MemoryIcon from "@material-ui/icons/Memory";
import PeopleIcon from "@material-ui/icons/People";
import AccountBoxIcon from "@material-ui/icons/AccountBox";
import LocalMallIcon from "@material-ui/icons/LocalMall";
import BrokenImageIcon from "@material-ui/icons/BrokenImage";
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import {
teamCountSelector,
getTeamsWithSearchThunk,
totalParticipantCountSelector,
} from "slices/event/teamAdminSlice";
import { clearFilters } from "slices/hardware/hardwareSlice";
import {
adminOrderSelectors,
getOrdersWithFilters,
setFilters,
adminOrderTotalSelector,
adminCheckedOutOrderTotalSelector,
} from "slices/order/adminOrderSlice";
import { OrderFilters } from "api/types";
import { useHistory } from "react-router-dom";

const Item = styled(Paper)(({ theme }) => ({
backgroundColor: "#fff",
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: "center",
color: theme.palette.text.secondary,
}));

const AdminDashboard = () => {
const dispatch = useDispatch();
const history = useHistory();
const allOrders = useSelector(adminOrderSelectors.selectAll);
const pendingFilter: OrderFilters = {
status: ["Submitted", "Ready for Pickup"],
};
dispatch(setFilters(pendingFilter));
dispatch(getOrdersWithFilters());
const orderQuantity = useSelector(adminOrderTotalSelector);
const count = useSelector(teamCountSelector);
const participants = useSelector(totalParticipantCountSelector);
const checkedOut = useSelector(adminCheckedOutOrderTotalSelector);
const numOrdersOnPage = 6;
const ordersLength =
allOrders.length <= numOrdersOnPage ? allOrders.length : numOrdersOnPage;
// TODO: Create selector for Broken/Lost Item

useEffect(() => {
const pendingFilter: OrderFilters = {
status: ["Submitted", "Ready for Pickup"],
};
dispatch(setFilters(pendingFilter));
dispatch(clearFilters());
dispatch(getOrdersWithFilters());
dispatch(getTeamsWithSearchThunk());
}, [dispatch]);
return (
<>
<Header />
<Typography variant="h1">{hackathonName} Admin Dashboard</Typography>
<Grid className={styles.dashboard}>
<div className={styles.section}>
<Typography className={styles.title}>Overview</Typography>
<div className={styles.dashboard}>
<Typography className={styles.overviewTitle} variant="h2">
{" "}
Overview{" "}
</Typography>
<Box sx={{ flexGrow: 1 }}>
<Grid wrap="nowrap" container spacing={2}>
<Grid item xs={5} md={3}>
<Item>
<Box display="flex" alignItems="center">
<MemoryIcon />{" "}
<Typography
variant="inherit"
className={styles.itemContent}
>
{checkedOut} item's checked out
</Typography>
</Box>
</Item>
</Grid>
<Grid item xs={5} md={3}>
<Item>
<Box display="flex" alignItems="center">
<PeopleIcon />{" "}
<Typography
variant="inherit"
className={styles.itemContent}
>
{participants} participants
</Typography>
</Box>
</Item>
</Grid>
<Grid item xs={5} md={3}>
<Item>
<Box display="flex" alignItems="center">
<AccountBoxIcon />{" "}
<Typography
variant="inherit"
className={styles.itemContent}
>
{count} teams
</Typography>
</Box>
</Item>
</Grid>
<Grid item xs={5} md={3}>
<Item>
<Box display="flex" alignItems="center">
<LocalMallIcon />{" "}
<Typography
variant="inherit"
className={styles.itemContent}
>
{orderQuantity} orders
</Typography>
</Box>
</Item>
</Grid>
<Grid item xs={5} md={3}>
<Item>
<Box display="flex" alignItems="center">
<BrokenImageIcon />{" "}
<Typography
variant="inherit"
className={styles.itemContent}
>
7 broken/lost items
</Typography>
</Box>
</Item>
</Grid>
</Grid>
</Box>
</div>

<div className={styles.section}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import {
teamAdminSelectors,
NUM_TEAM_LIMIT,
getTeamNextPage,
teamCountSelector,
totalParticipantCountSelector,
} from "slices/event/teamAdminSlice";
import { makeMockApiListResponse, makeStoreWithEntities, waitFor } from "testing/utils";
import { mockTeam, mockTeams } from "testing/mockData";
import { mockTeam, mockTeamMultiple, mockTeams, mockValidTeam } from "testing/mockData";
import { get, stripHostnameReturnFilters } from "api/api";
import { displaySnackbar } from "slices/ui/uiSlice";
import thunk, { ThunkDispatch } from "redux-thunk";
import { AnyAction } from "redux";
import configureStore from "redux-mock-store";
import { teamReducerName, teamSizeSelector } from "./teamSlice";

jest.mock("api/api", () => ({
...jest.requireActual("api/api"),
Expand Down Expand Up @@ -57,6 +60,18 @@ describe("Selectors", () => {
expect(isLoadingSelector(loadingTrueState)).toEqual(true);
expect(isLoadingSelector(loadingFalseState)).toEqual(false);
});
test("totalParticipantCountSelector", () => {
const store = makeStoreWithEntities({ teams: mockTeams });
const totalTeams = totalParticipantCountSelector(store.getState());
const totalProfiles = mockTeams.reduce((sum, team) => {
if (team.profiles) {
return sum + team.profiles.length;
} else {
return sum;
}
}, 0);
expect(totalTeams).toEqual(totalProfiles);
});
});

describe("getTeamsWithSearch thunk", () => {
Expand Down Expand Up @@ -92,6 +107,7 @@ describe("getTeamsWithSearch thunk", () => {
limit: NUM_TEAM_LIMIT,
});
expect(teamAdminSelectors.selectAll(store.getState())).toEqual(mockTeams);
expect(teamCountSelector(store.getState())).toEqual(mockTeams.length);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,14 @@ export const teamCountSelector = createSelector(
[teamAdminSliceSelector],
(teamAdminSlice) => teamAdminSlice.count
);

export const totalParticipantCountSelector = createSelector(
[teamAdminSelectors.selectAll],
(teamsList) => {
let count = 0;
for (let i = 0; i < teamsList.length; i++) {
count += teamsList[i].profiles.length;
}
return count;
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
errorSelector,
getOrdersWithFilters,
adminOrderSelectors,
adminOrderTotalWithFiltersSelector,
adminOrderTotalSelector,
adminCheckedOutOrderTotalSelector,
} from "slices/order/adminOrderSlice";
import { get } from "api/api";
import { makeMockApiListResponse, makeStoreWithEntities } from "testing/utils";
import { mockPendingOrders } from "testing/mockData";
import { mockCheckedOutOrders, mockOrders, mockPendingOrders } from "testing/mockData";
import { waitFor } from "@testing-library/react";

jest.mock("api/api", () => ({
Expand Down Expand Up @@ -52,11 +54,30 @@ describe("adminOrderSlice Selectors", () => {
expect(errorSelector(errorExistsState)).toEqual("exists");
expect(errorSelector(errorNullState)).toEqual(null);
});
test("adminOrderTotalSelector", () => {
test("adminOrderTotalWithFiltersSelector", () => {
const store = makeStoreWithEntities({ allOrders: mockPendingOrders });
const total = adminOrderTotalSelector(store.getState());
const total = adminOrderTotalWithFiltersSelector(store.getState());
expect(total).toEqual(mockPendingOrders.length);
});
// todo not working, doesnt select all orders
test("adminOrderTotalSelector", () => {
const store = makeStoreWithEntities({ allOrders: mockOrders });
const total = adminOrderTotalSelector(store.getState());
expect(total).toEqual(mockOrders.length);
});
test("adminCheckedOutOrderTotalSelector", () => {
const store = makeStoreWithEntities({ allOrders: mockCheckedOutOrders });
const total = adminCheckedOutOrderTotalSelector(store.getState());
const totalRequestedQuantity = mockCheckedOutOrders.reduce((sum, order) => {
return (
sum +
order.request.reduce((orderSum, item) => {
return orderSum + item.requested_quantity;
}, 0)
);
}, 0);
expect(total).toEqual(totalRequestedQuantity); // total number of orders in mockCheckedOutOrders
});
});
describe("getOrdersWithFilters Thunk", () => {
it("Updates the store on API success", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,24 @@ export const adminOrderNumStatusesSelector = createSelector(
(adminOrderSlice) => adminOrderSlice.numStatuses
);

export const adminOrderTotalSelector = createSelector(
export const adminOrderTotalWithFiltersSelector = createSelector(
[adminOrderSelectors.selectAll],
(orderItems) => orderItems.reduce((accum) => accum + 1, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change name of adminOrderTotalSelector to 'adminOrderTotalWithFiltersSelector', or similar.

);
//Todo this selector is being affected by filters
export const adminOrderTotalSelector = createSelector();

export const adminCheckedOutOrderTotalSelector = createSelector(
[adminOrderSelectors.selectAll],
(ordersList) => {
let count = 0;
for (let i = 0; i < ordersList.length; i++) {
if (ordersList[i].status === "Picked Up") {
count += ordersList[i].items.length;
}
}
return count;
}
);

export const { setFilters, clearFilters } = actions;