diff --git a/hackathon_site/dashboard/frontend/src/api/helpers.ts b/hackathon_site/dashboard/frontend/src/api/helpers.ts index 70f006753..2be346da4 100644 --- a/hackathon_site/dashboard/frontend/src/api/helpers.ts +++ b/hackathon_site/dashboard/frontend/src/api/helpers.ts @@ -75,7 +75,9 @@ export const teamOrderListSerialization = ( const hardwareInTableRow = Object.values(hardwareItems); if (hardwareInTableRow.length > 0) - (order.status === "Submitted" || order.status === "Ready for Pickup" + (order.status === "Submitted" || + order.status === "Ready for Pickup" || + order.status === "Packing" //TODO: Treating "Packing" orders (aka orders in progress of packing) as "Pending Orders" per table in participant side ? pendingOrders : checkedOutOrders ).push({ @@ -182,11 +184,14 @@ export const sortCheckedOutOrders = ( export const sortPendingOrders = (orders: OrderInTable[]): OrderInTable[] => { let ready_orders = []; let submitted_orders = []; + let packing_orders = []; // Added new array to ensure sorting of orders being packed accomodates for the orders with "packing" tag. This likely helps with the order display on the admin + participant table for (let order of orders) { if (order.status === "Ready for Pickup") { ready_orders.push(order); - } else { + } else if (order.status === "Submitted") { submitted_orders.push(order); + } else if (order.status === "Packing") { + packing_orders.push(order); } } ready_orders.sort((order1, order2) => { @@ -202,7 +207,20 @@ export const sortPendingOrders = (orders: OrderInTable[]): OrderInTable[] => { new Date(order2.updatedTime).valueOf() ); }); + // Sorting packing orders + packing_orders.sort((order1, order2) => { + return ( + new Date(order1.updatedTime).valueOf() - + new Date(order2.updatedTime).valueOf() + ); + }); - orders.splice(0, orders.length, ...submitted_orders, ...ready_orders); + orders.splice( + 0, + orders.length, + ...submitted_orders, + ...ready_orders, + ...packing_orders + ); return orders; }; diff --git a/hackathon_site/dashboard/frontend/src/api/orders.ts b/hackathon_site/dashboard/frontend/src/api/orders.ts index 6a168cfdd..bff20f563 100644 --- a/hackathon_site/dashboard/frontend/src/api/orders.ts +++ b/hackathon_site/dashboard/frontend/src/api/orders.ts @@ -3,8 +3,9 @@ import ReadyForPickupIcon from "assets/images/icons/statusIcons/readyforpickup-s 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 PackingIcon from "assets/images/icons/statusIcons/pending-status.svg"; +//TODO: A low-priority task, but perhaps looking into changing the PackingIcon to be a more accurate fit +//import InProgressIcon from "assets/images/icons/statusIcons/inprogress-status.svg"; import styles from "components/orders/OrdersTable/OrdersTable.module.scss"; @@ -14,8 +15,8 @@ export const statusIconMap: { [key: string]: string } = { PickedUp: PickedUpIcon, Cancelled: CancelledIcon, Returned: ReturnedIcon, - Pending: PendingIcon, - InProgress: InProgressIcon, + Packing: PackingIcon, + //InProgress: InProgressIcon, //Commented out since we likely don't need this status anymore (Packing should mean the same thing as "In Progress?") }; export const statusStylesMap: { [key: string]: string } = { @@ -24,6 +25,6 @@ export const statusStylesMap: { [key: string]: string } = { PickedUp: styles.PickedUpIcon, Cancelled: styles.CancelledIcon, Returned: styles.ReturnedIcon, - Pending: styles.PendingIcon, - InProgress: styles.InProgressIcon, + Packing: styles.PackingIcon, + //InProgress: styles.InProgressIcon, //Commented out since we likely don't need this status anymore (Packing should mean the same thing as "In Progress?") }; diff --git a/hackathon_site/dashboard/frontend/src/api/types.ts b/hackathon_site/dashboard/frontend/src/api/types.ts index 0855ea36a..41371a344 100644 --- a/hackathon_site/dashboard/frontend/src/api/types.ts +++ b/hackathon_site/dashboard/frontend/src/api/types.ts @@ -104,7 +104,8 @@ export type OrderStatus = | "Cancelled" | "Returned" | "Pending" - | "In Progress"; + | "In Progress" + | "Packing"; export type PartReturnedHealth = "Healthy" | "Heavily Used" | "Broken" | "Lost"; export type ItemsInOrder = Omit; diff --git a/hackathon_site/dashboard/frontend/src/assets/abstracts/_variables.scss b/hackathon_site/dashboard/frontend/src/assets/abstracts/_variables.scss index 70cada0e3..d8e0e3932 100644 --- a/hackathon_site/dashboard/frontend/src/assets/abstracts/_variables.scss +++ b/hackathon_site/dashboard/frontend/src/assets/abstracts/_variables.scss @@ -19,6 +19,9 @@ $colors: ( blueLight: #c3e1ef, purple: #800080, purpleLight: #cec4f2, + // added the pink colours. pink is now used to rep the "Updated at" UI tag. blue is now used to rep the "Packing" order tag (to mirror the order table on admin side created in prior merged PR [IEEE 269]) + pink: #ff007f, + pinkLight: #ffc0cb, ); $fonts: ( diff --git a/hackathon_site/dashboard/frontend/src/components/dashboard/ItemTable/ItemTable.tsx b/hackathon_site/dashboard/frontend/src/components/dashboard/ItemTable/ItemTable.tsx index c8a5ad6ff..b766fc9f8 100644 --- a/hackathon_site/dashboard/frontend/src/components/dashboard/ItemTable/ItemTable.tsx +++ b/hackathon_site/dashboard/frontend/src/components/dashboard/ItemTable/ItemTable.tsx @@ -95,9 +95,10 @@ export const CheckedOutTables = () => > { className={`${styles.chipOrange} ${styles.chip}`} /> ); + //TODO: How is the following case going to be triggered? + case "Packing": + return ( + } + label="Packing" + className={`${styles.chipBlue} ${styles.chip}`} //Made the colour of this tag blue to match the admin order table colour for the Pending tag + /> + ); case "Error": return ( ( +}: //additionalChipFormatting, //TODO: Commented out since not used +GeneralOrderTableTitleProps) => (
Order #{orderId} @@ -113,7 +123,7 @@ export const GeneralOrderTableTitle = ({ Updated at: , formatDateTime(updatedTime)]} icon={} - className={`${styles.chipBlue} ${styles.chip}`} + className={`${styles.chipPink} ${styles.chip}`} />
) : null} diff --git a/hackathon_site/dashboard/frontend/src/components/orders/OrdersFilter/OrderFilter.tsx b/hackathon_site/dashboard/frontend/src/components/orders/OrdersFilter/OrderFilter.tsx index 6d0225457..19d310316 100644 --- a/hackathon_site/dashboard/frontend/src/components/orders/OrdersFilter/OrderFilter.tsx +++ b/hackathon_site/dashboard/frontend/src/components/orders/OrdersFilter/OrderFilter.tsx @@ -105,6 +105,10 @@ const OrderFilter = ({ handleReset, handleSubmit }: FormikValues) => { status: "Returned", numOrders: numStatuses["Returned"], }, + { + status: "Packing", // TODO: Packing -> interpreted as "currently building". This alligns with table changes in IEEE 269 + numOrders: numStatuses["Packing"], + }, ]; return ( diff --git a/hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.module.scss b/hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.module.scss index eabbb68ac..b62d393da 100644 --- a/hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.module.scss +++ b/hackathon_site/dashboard/frontend/src/components/orders/OrdersTable/OrdersTable.module.scss @@ -48,7 +48,7 @@ background-color: #d9d9d9; } -.PendingIcon { +.PackingIcon { color: #2b7bbc; background-color: #c3e1ef; } diff --git a/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.test.tsx b/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.test.tsx index bb26d64d1..617e21a07 100644 --- a/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.test.tsx +++ b/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.test.tsx @@ -59,12 +59,15 @@ describe("", () => { } else { expect(getByText(/reject order/i)).toBeInTheDocument(); } - if (status === "Submitted") { + if (status === "Packing") { + /*TODO: Changed from status === "Submitted" to status === "Packing"*/ expect(getByText(/complete order/i)).toBeInTheDocument(); expect(queryByText(/picked up/i)).not.toBeInTheDocument(); - } else { + } else if (status === "Submitted") { expect(queryByText(/complete order/i)).not.toBeInTheDocument(); - expect(getByText(/picked up/i)).toBeInTheDocument(); + expect(queryByText(/ready for packing/i)).toBeInTheDocument(); + //expect(queryByText(/complete order/i)).not.toBeInTheDocument(); + //expect(getByText(/picked up/i)).toBeInTheDocument(); } } }); @@ -79,7 +82,8 @@ describe("", () => { const { queryByDisplayValue, getByDisplayValue } = within( getByTestId(`admin-simple-pending-order-${order.id}`) ); - if (order.status == "Submitted") { + if (order.status === "Packing") { + /*TODO: Changed from status === "Submitted" to status === "Packing"*/ order.hardwareInTableRow.forEach(({ id }) => { expect(getByDisplayValue(`hardware-${id}`)).toBeInTheDocument(); }); @@ -101,7 +105,9 @@ describe("", () => { }); mockPendingOrdersInTable - .filter(({ status }) => status === "Submitted") + .filter( + ({ status }) => status === "Packing" + ) /*TODO: Changed from status === "Submitted" to status === "Packing"*/ .map(({ id }) => { const { getByText } = within( getByTestId(`admin-simple-pending-order-${id}`) @@ -116,7 +122,9 @@ describe("", () => { }); const order = mockPendingOrdersInTable.find( - ({ status }) => status === "Submitted" + ({ status }) => + status === + "Packing" /*TODO: Changed from status === "Submitted" to status === "Packing"*/ ); if (order) { @@ -147,7 +155,9 @@ describe("", () => { }); const order = mockPendingOrdersInTable.find( - ({ status }) => status === "Submitted" + ({ status }) => + status === + "Packing" /*TODO: Changed from status === "Submitted" to status === "Packing"*/ ); if (order) { diff --git a/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.tsx b/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.tsx index ef0ff82b5..a734e738a 100644 --- a/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.tsx +++ b/hackathon_site/dashboard/frontend/src/components/teamDetail/SimpleOrderTables/SimpleOrderTables.tsx @@ -192,7 +192,7 @@ export const SimplePendingOrderFulfillmentTable = () => { @@ -202,7 +202,7 @@ export const SimplePendingOrderFulfillmentTable = () => { spacing={1} style={{ marginTop: "10px" }} > - {pendingOrder.status === "Submitted" && ( + {pendingOrder.status === "Submitted" && ( //Will not need to add this to the packing orders, since there is no reason to reject an order that is already being packed. )} + + {/* On Admin side: The code below adds a button that changes "Submitted" status => "Packing"*/} {pendingOrder.status === "Submitted" && ( - + + + + + + + + )} + + {/* On Admin side: The code below adds a button that changes "Packing" status => "Ready for Pickup"*/} + {pendingOrder.status === "Packing" && ( + + + + + {/*Commented out the code below since it caused a bug where if someone doesn't select all orders prior to pressing button, order status changes... */} + {/**/} + {/* updateOrder(*/} + {/* pendingOrder.id,*/} + {/* "Ready for Pickup"*/} + {/* )*/} + {/* }*/} + {/*>*/} + {/* Complete order*/} + {/**/} + + + )} {pendingOrder.status === "Ready for Pickup" && ( diff --git a/hackathon_site/dashboard/frontend/src/constants.js b/hackathon_site/dashboard/frontend/src/constants.js index 2ea30905d..c0554c1e3 100644 --- a/hackathon_site/dashboard/frontend/src/constants.js +++ b/hackathon_site/dashboard/frontend/src/constants.js @@ -3,5 +3,5 @@ export const adminGroup = "Hardware Site Admins"; export const minTeamSize = 2; export const maxTeamSize = 4; export const hardwareSignOutStartDate = new Date(2020, 9, 1, 23, 59); -export const hardwareSignOutEndDate = new Date(2023, 9, 30, 11, 59); +export const hardwareSignOutEndDate = new Date(2024, 9, 30, 11, 59); export const hssTestUserGroup = "HSS Test Users"; diff --git a/hackathon_site/dashboard/frontend/src/slices/order/adminOrderSlice.ts b/hackathon_site/dashboard/frontend/src/slices/order/adminOrderSlice.ts index 82fab7a4c..56ac5f1c8 100644 --- a/hackathon_site/dashboard/frontend/src/slices/order/adminOrderSlice.ts +++ b/hackathon_site/dashboard/frontend/src/slices/order/adminOrderSlice.ts @@ -16,6 +16,8 @@ interface numStatuses { "Picked Up"?: number; Cancelled?: number; Returned?: number; + //TODO: New entries added + Packing?: number; } interface adminOrderExtraState { @@ -153,6 +155,15 @@ const adminOrderSlice = createSlice({ "Returned", payload.results ); + + //TODO: COMMENTED OUT MOCK DATA HERE FOR NOW + // TODO: Is using payload.results essentially retrieving the "real data" from the (django?) backend? + // state.numStatuses["Pending"] = 3; //Not sure why the above line works fine... somehow feature was already implemented? + //state.numStatuses["Rejected"] = 21; + state.numStatuses["Packing"] = numOrdersByStatus( + "Packing", + payload.results + ); } adminOrderAdapter.setAll(state, payload.results); }); diff --git a/hackathon_site/dashboard/frontend/src/slices/order/teamOrderSlice.ts b/hackathon_site/dashboard/frontend/src/slices/order/teamOrderSlice.ts index 2281071ea..7af8ca8cf 100644 --- a/hackathon_site/dashboard/frontend/src/slices/order/teamOrderSlice.ts +++ b/hackathon_site/dashboard/frontend/src/slices/order/teamOrderSlice.ts @@ -278,7 +278,9 @@ export const pendingOrdersSelector = createSelector( (orders) => orders.filter( (order) => - order.status === "Submitted" || order.status === "Ready for Pickup" + order.status === "Submitted" || + order.status === "Ready for Pickup" || + order.status === "Packing" ) ); diff --git a/hackathon_site/dashboard/frontend/src/testing/mockData.tsx b/hackathon_site/dashboard/frontend/src/testing/mockData.tsx index 531cf58fe..0a9a9edbb 100644 --- a/hackathon_site/dashboard/frontend/src/testing/mockData.tsx +++ b/hackathon_site/dashboard/frontend/src/testing/mockData.tsx @@ -845,6 +845,21 @@ export const mockPendingOrdersInTable: OrderInTable[] = [ createdTime: "2021-10-17T18:28:44.691969-03:00", updatedTime: "2021-10-17T18:28:44.691969-06:00", }, + + /*TODO NOTE: Removing this new mock order would mean all dashboard test pass. Currently this causes test issues where the cancel order button doesn't work*/ + { + id: 11, + hardwareInTableRow: [ + { + id: 10, + quantityRequested: 2, + quantityGranted: 1, + }, + ], + status: "Packing", + createdTime: "2024-01-17T18:28:44.691969-03:00", + updatedTime: "2024-12-17T18:28:44.691969-06:00", + }, { id: 4, hardwareInTableRow: [ diff --git a/hackathon_site/hardware/migrations/0012_alter_order_status.py b/hackathon_site/hardware/migrations/0012_alter_order_status.py new file mode 100644 index 000000000..343dff3da --- /dev/null +++ b/hackathon_site/hardware/migrations/0012_alter_order_status.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.15 on 2024-01-01 04:52 + +from django.db import migrations, models + +# TODO: Between this, the 0013 and 0011 .py files, decide which to keep +class Migration(migrations.Migration): + + dependencies = [ + ("hardware", "0011_alter_order_team"), + ] + + operations = [ + migrations.AlterField( + model_name="order", + name="status", + field=models.CharField( + choices=[ + ("Submitted", "Submitted"), + ("Ready for Pickup", "Ready for Pickup"), + ("Picked Up", "Picked Up"), + ("Cancelled", "Cancelled"), + ("Returned", "Returned"), + ("Pending", "Pending"), + ("Rejected", "Rejected"), + ], + default="Submitted", + max_length=64, + ), + ), + ] diff --git a/hackathon_site/hardware/migrations/0013_alter_order_status.py b/hackathon_site/hardware/migrations/0013_alter_order_status.py new file mode 100644 index 000000000..e706d0398 --- /dev/null +++ b/hackathon_site/hardware/migrations/0013_alter_order_status.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.15 on 2024-01-04 05:03 + +from django.db import migrations, models + +# TODO: Between this, the 0012 and 0011 .py files, decide which to keep +class Migration(migrations.Migration): + + dependencies = [ + ("hardware", "0012_alter_order_status"), + ] + + operations = [ + migrations.AlterField( + model_name="order", + name="status", + field=models.CharField( + choices=[ + ("Submitted", "Submitted"), + ("Ready for Pickup", "Ready for Pickup"), + ("Picked Up", "Picked Up"), + ("Cancelled", "Cancelled"), + ("Returned", "Returned"), + ("Packing", "Packing"), + ], + default="Submitted", + max_length=64, + ), + ), + ] diff --git a/hackathon_site/hardware/models.py b/hackathon_site/hardware/models.py index 241e5ed9e..82a99e6d8 100644 --- a/hackathon_site/hardware/models.py +++ b/hackathon_site/hardware/models.py @@ -107,6 +107,9 @@ class Order(models.Model): ("Picked Up", "Picked Up"), ("Cancelled", "Cancelled"), ("Returned", "Returned"), + ("Packing", "Packing",), + # TODO: ADDED NEW ENTRIES HERE. + # See ref: https://github.com/ieeeuoft/hackathon-template/pull/293/files#diff-b5fcbda10cee3497387c38bdc3a12e6281d696a490b4bbbbce23e0c052baad4d ] hardware = models.ManyToManyField(Hardware, through=OrderItem) diff --git a/hackathon_site/hardware/serializers.py b/hackathon_site/hardware/serializers.py index 130ab7468..5688e5efb 100644 --- a/hackathon_site/hardware/serializers.py +++ b/hackathon_site/hardware/serializers.py @@ -158,11 +158,12 @@ def get_team_code(obj: Order): return obj.team.team_code if obj.team else None -class OrderChangeSerializer(OrderListSerializer): +class OrderChangeSerializer(OrderListSerializer): # TODO: Modified flow of serializers change_options = { - "Submitted": ["Cancelled", "Ready for Pickup"], + "Submitted": ["Cancelled", "Packing"], "Ready for Pickup": ["Picked Up"], "Picked Up": ["Returned"], + "Packing": ["Ready for Pickup"], } class Meta: diff --git a/hackathon_site/hardware/views.py b/hackathon_site/hardware/views.py index c4d1a3992..55c3540ec 100644 --- a/hackathon_site/hardware/views.py +++ b/hackathon_site/hardware/views.py @@ -40,11 +40,14 @@ logger = logging.getLogger(__name__) +# TODO: What is the difference between ORDER_STATUS_MSG and ORDER_STATUS_CLOSING_MSG + ORDER_STATUS_MSG = { "Ready for Pickup": "is Ready for Pickup!", "Picked Up": "has been Picked Up!", "Cancelled": f"was Cancelled by a {settings.HACKATHON_NAME} Exec.", "Returned": f"has been returned.", + "Packing": f"is being packed!", } ORDER_STATUS_CLOSING_MSG = { @@ -52,6 +55,7 @@ "Picked Up": "Take good care of your hardware and Happy Hacking! Remember to return the items when you are finished using them.", "Cancelled": f"A {settings.HACKATHON_NAME} exec will be in contact with you shortly. If you don't hear back from them soon, please go to the Tech Team Station for more information on why your order was cancelled.", "Returned": f"Thank you for returning all hardware items!", + "Packing": f"Your hardware order is being packed!", }