-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into IEEE-259-add-description-box-on-teams-hom…
…epage
- Loading branch information
Showing
21 changed files
with
976 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import SubmittedIcon from "assets/images/icons/statusIcons/unfulfilled-status.svg"; | ||
import ReadyForPickupIcon from "assets/images/icons/statusIcons/readyforpickup-status.svg"; | ||
import PickedUpIcon from "assets/images/icons/statusIcons/checkout-status.svg"; | ||
import CancelledIcon from "assets/images/icons/statusIcons/cancelled-status.svg"; | ||
import ReturnedIcon from "assets/images/icons/statusIcons/checkout-status.svg"; | ||
import PendingIcon from "assets/images/icons/statusIcons/pending-status.svg"; | ||
import InProgressIcon from "assets/images/icons/statusIcons/inprogress-status.svg"; | ||
|
||
import styles from "components/orders/OrdersTable/OrdersTable.module.scss"; | ||
|
||
export const statusIconMap: { [key: string]: string } = { | ||
Submitted: SubmittedIcon, | ||
ReadyforPickup: ReadyForPickupIcon, | ||
PickedUp: PickedUpIcon, | ||
Cancelled: CancelledIcon, | ||
Returned: ReturnedIcon, | ||
Pending: PendingIcon, | ||
InProgress: InProgressIcon, | ||
}; | ||
|
||
export const statusStylesMap: { [key: string]: string } = { | ||
Submitted: styles.SubmittedIcon, | ||
ReadyforPickup: styles.ReadyforPickupIcon, | ||
PickedUp: styles.PickedUpIcon, | ||
Cancelled: styles.CancelledIcon, | ||
Returned: styles.ReturnedIcon, | ||
Pending: styles.PendingIcon, | ||
InProgress: styles.InProgressIcon, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
...ite/dashboard/frontend/src/assets/images/icons/statusIcons/cancelled-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions
3
...site/dashboard/frontend/src/assets/images/icons/statusIcons/checkout-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions
3
...te/dashboard/frontend/src/assets/images/icons/statusIcons/inprogress-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions
4
..._site/dashboard/frontend/src/assets/images/icons/statusIcons/pending-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions
3
...ashboard/frontend/src/assets/images/icons/statusIcons/readyforpickup-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions
3
...e/dashboard/frontend/src/assets/images/icons/statusIcons/unfulfilled-status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions
59
hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@import "../../../assets/abstracts/mixins"; | ||
@import "../../../assets/abstracts/variables"; | ||
|
||
.container { | ||
display: flex; | ||
flex-direction: row; | ||
align-content: center; | ||
justify-content: flex-start; | ||
|
||
width: 100%; | ||
padding: 4px; | ||
border-radius: 50px; | ||
} | ||
|
||
.gridContainer { | ||
background-color: #ffffff; | ||
} | ||
|
||
.statusIcon { | ||
width: 12px; | ||
margin-left: 5px; | ||
margin-right: 10px; | ||
} | ||
|
||
// for OrdersTable | ||
.SubmittedIcon { | ||
color: #b7941e; | ||
background-color: #ffe899; | ||
} | ||
|
||
.ReadyforPickupIcon { | ||
color: #43a047; | ||
background-color: #c1edc1; | ||
} | ||
|
||
.PickedUpIcon { | ||
color: #757575; | ||
background-color: #d9d9d9; | ||
} | ||
|
||
.CancelledIcon { | ||
color: #b00020; | ||
background-color: #ebbcbc; | ||
} | ||
|
||
.ReturnedIcon { | ||
color: #757575; | ||
background-color: #d9d9d9; | ||
} | ||
|
||
.PendingIcon { | ||
color: #2b7bbc; | ||
background-color: #c3e1ef; | ||
} | ||
|
||
.InProgressIcon { | ||
color: #ffa000; | ||
background-color: #ffe3b4; | ||
} |
98 changes: 98 additions & 0 deletions
98
hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import React from "react"; | ||
import { fireEvent, render, waitFor } from "testing/utils"; | ||
import { mockPendingOrders } from "testing/mockData"; | ||
import { OrdersTable } from "./OrdersTable"; | ||
import { format, parseISO } from "date-fns"; // to parse date | ||
import { orderQtyValueGetter } from "./OrdersTable"; | ||
import { createMemoryHistory } from "history"; | ||
import { Router } from "react-router-dom"; | ||
|
||
describe("Orders Table", () => { | ||
test("renders order table", () => { | ||
const { container } = render(<OrdersTable ordersData={mockPendingOrders} />); | ||
// find the rendered Data Grid | ||
const dataGrid = container.querySelector(".MuiDataGrid-root"); | ||
expect(dataGrid).toBeInTheDocument(); | ||
}); | ||
|
||
test("Displays the correct number of rows", () => { | ||
const { container } = render(<OrdersTable ordersData={mockPendingOrders} />); | ||
|
||
const rows = container.querySelector(".MuiTablePagination-displayedRows"); | ||
const rowsText = rows?.textContent || ""; // get the text content of the element | ||
// returns 1-4 of 4 | ||
|
||
// regex to extract numbers from the text | ||
const numbersInText = rowsText.split(" "); // get the last number 4 | ||
expect(numbersInText ? parseInt(numbersInText[2]) : 0).toEqual( | ||
mockPendingOrders.length | ||
); | ||
}); | ||
|
||
test("Displays data accurately", () => { | ||
const { container } = render( | ||
<OrdersTable ordersData={[mockPendingOrders[0]]} /> | ||
); // select the first row | ||
|
||
const rows = container.querySelectorAll("div.MuiDataGrid-row"); | ||
rows.forEach((row, rowIndex) => { | ||
// Query for the cells in each row | ||
const cells = row.querySelectorAll("div.MuiDataGrid-cell"); | ||
|
||
expect(cells.length).toBe(6); // 6 fields are displayed in datagrid | ||
|
||
// Access and assert the cell data | ||
expect(cells[0].textContent).toBe( | ||
mockPendingOrders[rowIndex].id.toString() | ||
); | ||
expect(cells[1].textContent).toBe( | ||
format(parseISO(mockPendingOrders[rowIndex].created_at), "MMM d, HH:mm") | ||
); | ||
expect(cells[2].textContent).toBe(mockPendingOrders[rowIndex].team_id); | ||
expect(cells[3].textContent).toBe(mockPendingOrders[rowIndex].team_code); | ||
expect(cells[4].textContent).toBe( | ||
mockPendingOrders[rowIndex].items?.length.toString() | ||
); | ||
expect(cells[5].textContent).toBe(mockPendingOrders[rowIndex].status); | ||
}); | ||
}); | ||
|
||
test("ValueGetter caluclates order quantity correctly", () => { | ||
let params = { | ||
value: [ | ||
{ | ||
id: 6, | ||
hardware_id: 3, | ||
part_returned_health: null, | ||
}, | ||
{ | ||
id: 7, | ||
hardware_id: 4, | ||
part_returned_health: null, | ||
}, | ||
], | ||
}; // initialize grid value getter params | ||
|
||
const result = orderQtyValueGetter(params); | ||
expect(result).toBe(2); | ||
}); | ||
|
||
test("Handles double row click event", async () => { | ||
const history = createMemoryHistory(); | ||
|
||
const { container } = render( | ||
<Router history={history}> | ||
<OrdersTable ordersData={mockPendingOrders} /> | ||
</Router> | ||
); | ||
|
||
const rows = container.querySelectorAll("div.MuiDataGrid-row"); | ||
|
||
fireEvent.doubleClick(rows[0]); | ||
|
||
await waitFor(() => { | ||
// Assert that the URL has changed to the expected path | ||
expect(history.location.pathname).toBe("/teams/IEEE"); // Replace with your expected URL | ||
}); | ||
}); | ||
}); |
132 changes: 132 additions & 0 deletions
132
hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import React from "react"; | ||
import { | ||
DataGrid, | ||
GridCallbackDetails, | ||
GridColDef, | ||
GridEventListener, | ||
GridRowParams, | ||
MuiEvent, | ||
} from "@mui/x-data-grid"; | ||
import { ItemsInOrder, Order } from "api/types"; | ||
import { format, parseISO } from "date-fns"; // to parse date | ||
import { statusIconMap, statusStylesMap } from "api/orders"; | ||
import styles from "./OrdersTable.module.scss"; | ||
import { useHistory } from "react-router-dom"; | ||
|
||
// magic numbers | ||
const pageSizeOptions = [5, 10, 25]; // items displayed per page | ||
const paginationModel = { pageSize: 25, page: 0 }; // defauly number of rows displayed per page | ||
|
||
interface OrdersTableProps { | ||
ordersData: Order[]; | ||
} | ||
|
||
interface IOrderStateIcon { | ||
status: string; | ||
} | ||
|
||
export const orderQtyValueGetter = (params: any) => { | ||
const items = params?.value as ItemsInOrder[] | undefined; | ||
return Array.isArray(items) ? items.length : 0; | ||
}; | ||
|
||
const OrderStateIcon = ({ status }: IOrderStateIcon) => { | ||
const filterState: string = status.replace(/\s+/g, ""); | ||
const styleIcon = statusStylesMap[filterState]; | ||
const iconSrc = statusIconMap[filterState]; | ||
|
||
return ( | ||
<div className={styles.container}> | ||
<div className={`${styles.container} ${styleIcon}`}> | ||
<img | ||
src={iconSrc} | ||
className={styles.statusIcon} | ||
alt={`${status} icon`} | ||
/> | ||
{status} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
const handleEvent = ( | ||
params: GridRowParams, // GridRowParams | ||
event: MuiEvent<React.MouseEvent<HTMLElement>>, // MuiEvent<React.MouseEvent<HTMLElement>> | ||
details: GridCallbackDetails, | ||
navigateCallback: (path: string) => void | ||
) => { | ||
const path = `/teams/${params.row.team_code}`; | ||
navigateCallback(path); | ||
}; | ||
|
||
const OrdersTable = ({ ordersData }: OrdersTableProps) => { | ||
const history = useHistory(); | ||
|
||
const handleDoubleRowClick: GridEventListener<"rowClick"> = ( | ||
params: GridRowParams, | ||
event: MuiEvent<React.MouseEvent<HTMLElement>>, | ||
details: GridCallbackDetails | ||
) => { | ||
handleEvent(params, event, details, (path) => { | ||
history.push(path); // Call the navigateCallback | ||
}); | ||
}; | ||
|
||
const columns: GridColDef[] = [ | ||
{ field: "id", headerName: "ID", width: 25, flex: 1 }, | ||
{ | ||
field: "created_at", | ||
headerName: "Time Ordered", | ||
flex: 1, | ||
valueFormatter: (params) => { | ||
const time = params.value as string; | ||
const date = parseISO(time); | ||
const formattedTime = format(date, "MMM d, HH:mm"); | ||
return formattedTime; | ||
}, | ||
}, | ||
{ field: "team_id", headerName: "Team ID", flex: 1, minWidth: 100 }, | ||
{ field: "team_code", headerName: "Team", flex: 1 }, | ||
{ | ||
field: "items", | ||
headerName: "Order Qty", | ||
flex: 1, | ||
valueGetter: orderQtyValueGetter, | ||
}, | ||
{ | ||
field: "status", | ||
headerName: "Status", | ||
minWidth: 250, | ||
renderCell: (params) => <OrderStateIcon status={params.value} />, | ||
}, | ||
{ field: "updated_at", headerName: "Updated At" }, | ||
{ field: "request", headerName: "Request" }, | ||
]; | ||
|
||
return ( | ||
<> | ||
<div style={{ width: "100%", height: "700px" }}> | ||
<DataGrid | ||
className={styles.gridContainer} | ||
rows={ordersData} | ||
columns={columns} | ||
autoPageSize={true} // adjusts page size to fit available area | ||
pageSizeOptions={pageSizeOptions} | ||
columnVisibilityModel={{ | ||
// hide specific columns | ||
updated_at: false, | ||
request: false, | ||
}} | ||
initialState={{ | ||
pagination: { | ||
paginationModel: paginationModel, | ||
}, | ||
}} | ||
onRowDoubleClick={handleDoubleRowClick} | ||
/> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export { OrdersTable }; |
Oops, something went wrong.