diff --git a/apps/backend/src/migrations/1764816885341-RemoveUnusedStatuses.ts b/apps/backend/src/migrations/1764816885341-RemoveUnusedStatuses.ts index 6419e233..4c35fd0f 100644 --- a/apps/backend/src/migrations/1764816885341-RemoveUnusedStatuses.ts +++ b/apps/backend/src/migrations/1764816885341-RemoveUnusedStatuses.ts @@ -1,25 +1,24 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm'; export class RemoveUnusedStatuses1764816885341 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE allocations DROP COLUMN IF EXISTS status;`, + ); + await queryRunner.query( + `ALTER TABLE donation_items DROP COLUMN IF EXISTS status;`, + ); + } - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE allocations DROP COLUMN IF EXISTS status;` - ); - await queryRunner.query( - `ALTER TABLE donation_items DROP COLUMN IF EXISTS status;` - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(` + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` ALTER TABLE allocations ADD COLUMN status VARCHAR(25) NOT NULL DEFAULT 'pending'; `); - await queryRunner.query(` + await queryRunner.query(` ALTER TABLE donation_items ADD COLUMN status VARCHAR(25) NOT NULL DEFAULT 'available'; `); - } + } } diff --git a/apps/backend/src/orders/order.controller.ts b/apps/backend/src/orders/order.controller.ts index b43b8501..29d65fc3 100644 --- a/apps/backend/src/orders/order.controller.ts +++ b/apps/backend/src/orders/order.controller.ts @@ -24,8 +24,9 @@ export class OrdersController { private readonly allocationsService: AllocationsService, ) {} - // Called like: /?status=pending&pantryName=Test%20Pantry&pantryName=Test%20Pantry%2 + // Called like: /?status=pending&pantryName=Test%20Pantry&pantryName=Test%20Pantry%202 // %20 is the URL encoded space character + // This gets all pantries with the name Test Pantry or Test Pantry 2 that have a pending status @Get('/') async getAllOrders( @Query('status') status?: string, @@ -47,21 +48,21 @@ export class OrdersController { return this.ordersService.getPastOrders(); } - @Get(':orderId/pantry') + @Get('/:orderId/pantry') async getPantryFromOrder( @Param('orderId', ParseIntPipe) orderId: number, ): Promise { return this.ordersService.findOrderPantry(orderId); } - @Get(':orderId/request') + @Get('/:orderId/request') async getRequestFromOrder( @Param('orderId', ParseIntPipe) orderId: number, ): Promise { return this.ordersService.findOrderFoodRequest(orderId); } - @Get(':orderId/manufacturer') + @Get('/:orderId/manufacturer') async getManufacturerFromOrder( @Param('orderId', ParseIntPipe) orderId: number, ): Promise { @@ -82,7 +83,7 @@ export class OrdersController { return this.ordersService.findOrderByRequest(requestId); } - @Get(':orderId/allocations') + @Get('/:orderId/allocations') async getAllAllocationsByOrder( @Param('orderId', ParseIntPipe) orderId: number, ) { diff --git a/apps/backend/src/orders/order.service.ts b/apps/backend/src/orders/order.service.ts index 8a36819f..05f37bca 100644 --- a/apps/backend/src/orders/order.service.ts +++ b/apps/backend/src/orders/order.service.ts @@ -16,6 +16,7 @@ export class OrdersService { const qb = this.repo .createQueryBuilder('order') .leftJoinAndSelect('order.pantry', 'pantry') + .leftJoinAndSelect('pantry.volunteers', 'volunteers') .select([ 'order.orderId', 'order.status', @@ -23,6 +24,9 @@ export class OrdersService { 'order.shippedAt', 'order.deliveredAt', 'pantry.pantryName', + 'volunteers.id', + 'volunteers.firstName', + 'volunteers.lastName', ]); if (filters?.status) { diff --git a/apps/backend/src/pantries/dtos/pantry-application.dto.ts b/apps/backend/src/pantries/dtos/pantry-application.dto.ts index 42510915..c7473b0f 100644 --- a/apps/backend/src/pantries/dtos/pantry-application.dto.ts +++ b/apps/backend/src/pantries/dtos/pantry-application.dto.ts @@ -52,7 +52,7 @@ export class PantryApplicationDto { @IsNotEmpty() @MaxLength(255) emailContactOther?: string; - + @IsOptional() @IsString() @IsNotEmpty() diff --git a/apps/frontend/src/app.tsx b/apps/frontend/src/app.tsx index 90be09d1..c39631b4 100644 --- a/apps/frontend/src/app.tsx +++ b/apps/frontend/src/app.tsx @@ -23,6 +23,7 @@ import DonationManagement from '@containers/donationManagement'; import AdminDonation from '@containers/adminDonation'; import { pantryIdLoader } from '@loaders/pantryIdLoader'; import Homepage from '@containers/homepage'; +import AdminOrderManagement from '@containers/adminOrderManagement'; const router = createBrowserRouter([ { @@ -97,6 +98,10 @@ const router = createBrowserRouter([ path: '/admin-donation', element: , }, + { + path: '/admin-order-management', + element: , + }, { path: '/volunteer-management', element: , diff --git a/apps/frontend/src/components/forms/orderDetailsModal.tsx b/apps/frontend/src/components/forms/orderDetailsModal.tsx new file mode 100644 index 00000000..339be715 --- /dev/null +++ b/apps/frontend/src/components/forms/orderDetailsModal.tsx @@ -0,0 +1,150 @@ +import React, { useState, useEffect } from 'react'; +import { + Text, + Dialog, + CloseButton, + Flex, + Textarea, + Field, + Tag, +} from '@chakra-ui/react'; +import ApiClient from '@api/apiClient'; +import { FoodRequest, Order } from 'types/types'; +import { formatDate } from '@utils/utils'; + +interface OrderDetailsModalProps { + order: Order; + isOpen: boolean; + onClose: () => void; +} + +const OrderDetailsModal: React.FC = ({ + order, + isOpen, + onClose, +}) => { + const [foodRequest, setFoodRequest] = useState(null); + + useEffect(() => { + if (isOpen) { + const fetchData = async () => { + try { + const foodRequestData = await ApiClient.getFoodRequestFromOrder( + order.orderId, + ); + setFoodRequest(foodRequestData); + } catch (error) { + console.error('Error fetching food request details:', error); + } + }; + + fetchData(); + } + }, [isOpen, order.orderId]); + + return ( + { + if (!e.open) onClose(); + }} + closeOnInteractOutside + > + + + + + + Order {order.orderId} + + + + {foodRequest && ( + <> + + {order.pantry.pantryName} + + + Requested {formatDate(foodRequest.requestedAt)} + + + + + + Size of Shipment + + + + {foodRequest.requestedSize} + + + + + + + Food Type(s) + + + + {foodRequest.requestedItems.map((item, index) => ( + + {item} + + ))} + + + + + + + Additional Information + + +