Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a3ec50a
Updated logic for moving fields
Tarun-Nagesh Feb 8, 2026
f4a22c2
Added/changed tests
Tarun-Nagesh Feb 8, 2026
bb71e3e
Some scuffed workaround, unsure if it has any other implications
Tarun-Nagesh Feb 8, 2026
4dd7a44
cleanup and comments
Tarun-Nagesh Feb 19, 2026
aee1b48
merging main
Tarun-Nagesh Feb 20, 2026
fda0ece
linting
Tarun-Nagesh Feb 20, 2026
4b16f21
fixed test
Tarun-Nagesh Feb 20, 2026
e1dc7c0
Added status back to FoodRequest
Tarun-Nagesh Feb 20, 2026
e210752
order management frontend
Juwang110 Feb 23, 2026
f2d5e75
confirm delivery modal
Juwang110 Feb 23, 2026
198de70
finishing touches, file upload confirmation functionality
Juwang110 Feb 25, 2026
904d839
Merge branch 'main' into jw/order-management-homepage
Juwang110 Feb 25, 2026
f63a269
Merge branch 'main' into jw/order-management-homepage
Juwang110 Feb 26, 2026
b11aa32
cleanup
Juwang110 Feb 26, 2026
179b6b6
minor changes
Juwang110 Feb 27, 2026
5c381f1
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 7, 2026
53251c0
adding order details modal
Juwang110 Mar 8, 2026
414be55
comments
Juwang110 Mar 9, 2026
1ee908e
removing usage of confirmdelivery
Juwang110 Mar 9, 2026
b5c8d8b
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 9, 2026
8b4da4c
rendering modals once
Juwang110 Mar 9, 2026
d93c28c
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 10, 2026
d2cfa1a
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 12, 2026
49758fd
comments
Juwang110 Mar 12, 2026
f96f5bd
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 14, 2026
a0d0e71
comments
Juwang110 Mar 14, 2026
bc4d543
restricting date received so not in future
Juwang110 Mar 15, 2026
5c99a02
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 16, 2026
fcfb508
using new alert hook
Juwang110 Mar 16, 2026
322c646
comments
Juwang110 Mar 16, 2026
081b015
comment
Juwang110 Mar 17, 2026
62e7509
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 18, 2026
68d1e30
comments
Juwang110 Mar 18, 2026
e8bc4ea
proper order of rows for pantry and admin order management
Juwang110 Mar 19, 2026
3b2d075
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 19, 2026
bfe2eb5
Merge branch 'main' into jw/order-management-homepage
Juwang110 Mar 22, 2026
869ad8e
final comments
Juwang110 Mar 22, 2026
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
33 changes: 33 additions & 0 deletions apps/frontend/src/api/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
OrderSummary,
UserDto,
OrderDetails,
ConfirmDeliveryDto,
FoodRequestSummaryDto,
} from 'types/types';

Expand Down Expand Up @@ -158,6 +159,12 @@ export class ApiClient {
.then((response) => response.data);
}

public async getPantryOrders(pantryId: number): Promise<OrderSummary[]> {
Comment thread
sam-schu marked this conversation as resolved.
Outdated
return this.axiosInstance
.get(`/api/pantries/${pantryId}/orders`)
.then((response) => response.data);
}

public async getPantry(pantryId: number): Promise<Pantry> {
return this.get(`/api/pantries/${pantryId}`) as Promise<Pantry>;
}
Expand Down Expand Up @@ -211,6 +218,32 @@ export class ApiClient {
.then((response) => response.data);
}

public async confirmOrderDelivery(
Comment thread
Juwang110 marked this conversation as resolved.
orderId: number,
dto: ConfirmDeliveryDto,
photos: File[],
): Promise<Order> {
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
const formData = new FormData();

// DTO fields
formData.append('dateReceived', dto.dateReceived);
if (dto.feedback) {
formData.append('feedback', dto.feedback);
}

// files (must be key = "photos")
for (const file of photos) {
formData.append('photos', file);
}

const { data } = await this.axiosInstance.patch(
`/api/orders/${orderId}/confirm-delivery`,
formData,
);

return data;
}

public async postManufacturer(
data: ManufacturerApplicationDto,
): Promise<AxiosResponse<void>> {
Expand Down
9 changes: 9 additions & 0 deletions apps/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import ForgotPasswordPage from '@containers/forgotPasswordPage';
import ProtectedRoute from '@components/protectedRoute';
import Unauthorized from '@containers/unauthorized';
import { Authenticator } from '@aws-amplify/ui-react';
import PantryOrderManagement from '@containers/pantryOrderManagement';
import FoodManufacturerApplication from '@containers/foodManufacturerApplication';
import { submitManufacturerApplicationForm } from '@components/forms/manufacturerApplicationForm';

Expand Down Expand Up @@ -198,6 +199,14 @@ const router = createBrowserRouter([
</ProtectedRoute>
),
},
{
path: '/pantry-order-management',
element: (
<ProtectedRoute>
<PantryOrderManagement />
</ProtectedRoute>
),
},
{
path: '/confirm-delivery',
action: submitDeliveryConfirmationFormModal,
Expand Down
4 changes: 4 additions & 0 deletions apps/frontend/src/chakra-ui.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ declare module '@chakra-ui/react' {
extends ComponentPropsStrictChildren {}
export interface MenuRadioItemProps extends ComponentPropsLenientChildren {}

// FileUpload components
export interface FileUploadDropzoneProps
extends ComponentPropsLenientChildren {}

// Dialog components
export interface DialogCloseTriggerProps
extends ComponentPropsStrictChildren {}
Expand Down
228 changes: 228 additions & 0 deletions apps/frontend/src/components/forms/orderReceivedActionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import React, { useState } from 'react';
import {
Flex,
Button,
Textarea,
Text,
Dialog,
Box,
Field,
CloseButton,
Input,
FileUpload,
Icon,
} from '@chakra-ui/react';
import { Upload } from 'lucide-react';
import { ConfirmDeliveryDto } from 'types/types';
import apiClient from '@api/apiClient';

interface OrderReceivedActionModalProps {
orderId: number;
isOpen: boolean;
onClose: () => void;
onSuccess: () => void;
}

const MAX_FILES = 10;

const OrderReceivedActionModal: React.FC<OrderReceivedActionModalProps> = ({
orderId,
isOpen,
onClose,
onSuccess,
}) => {
const [alertMessage, setAlertMessage] = useState<string>('');
const [feedback, setFeedback] = useState<string>('');
const [dateReceived, setDateReceived] = useState<string>('');
const [photos, setPhotos] = useState<File[]>([]);

const isFormValid = dateReceived !== '';

const resetForm = () => {
setAlertMessage('');
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
setFeedback('');
setDateReceived('');
setPhotos([]);
};

const handleSubmit = async () => {
try {
const dto: ConfirmDeliveryDto = {
dateReceived: new Date(dateReceived).toISOString(),
feedback: feedback,
};

await apiClient.confirmOrderDelivery(orderId, dto, photos);

setAlertMessage('Delivery Confirmed');
resetForm();
onSuccess();
onClose();
} catch (err) {
setAlertMessage('Delivery could not be confirmed.');
resetForm();
onClose();
}
};

return (
<Dialog.Root
open={isOpen}
size="xl"
onOpenChange={(e: { open: boolean }) => {
if (!e.open) onClose();
}}
closeOnInteractOutside
>
{alertMessage && (
// TODO: add Justin's alert component/uncomment below out and remove text component
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
// <FloatingAlert message={alertMessage} status="error" timeout={6000} />
<Text>{alertMessage}</Text>
)}
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content maxW={650}>
<Dialog.Header pb={0} mt={2}>
<Dialog.Title
color="black"
fontSize="lg"
fontWeight={700}
fontFamily="inter"
>
Action Required
</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<Text
mb={5}
color="#52525B"
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
textStyle="p2"
pt={0}
mt={2}
textAlign={'left'}
>
As this order arrives, please confirm the donation receipt and
delivery of the order by filling out the details below.
</Text>
<Box>
<Field.Root required mb={4}>
<Field.Label>
<Text textStyle="p2" fontWeight={600} color="neutral.800">
Date Received
</Text>
</Field.Label>
<Input
type="date"
textStyle="p2"
w="full"
bg="white"
borderColor="neutral.100"
color="neutral.700"
borderWidth="1px"
borderRadius="4px"
onChange={(e) => setDateReceived(e.target.value)}
value={dateReceived}
/>
</Field.Root>

<Field.Root mb={4}>
<Field.Label>
<Text textStyle="p2" fontWeight={600} color="neutral.800">
Feedback
</Text>
</Field.Label>
<Textarea
pl={2.5}
size="lg"
textStyle="p2"
color="neutral.800"
borderColor="neutral.100"
minH={150}
value={feedback}
onChange={(e) => {
const inputText = e.target.value;
const words = inputText.trim().split(/\s+/);

if (words.length <= 250) {
setFeedback(e.target.value);
} else {
alert('Exceeded word limit');
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
}
}}
/>

<Field.HelperText color="neutral.600">
Max 250 words
</Field.HelperText>
</Field.Root>

<Field.Root mb={4}>
<Field.Label>
<Text textStyle="p2" fontWeight={600} color="neutral.800">
Photos
</Text>
</Field.Label>
<FileUpload.Root
accept={['image/png', 'image/jpeg', 'image/jpg']}
alignItems="stretch"
maxFiles={MAX_FILES}
onFileChange={(e: any) => {
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
const files: File[] = e?.acceptedFiles ?? [];
setPhotos(files);
}}
>
<FileUpload.HiddenInput />
<FileUpload.Dropzone
borderColor="neutral.100"
borderRadius="4px"
borderStyle="solid"
borderWidth="1px"
minH="150px"
>
<Icon size="md" color="fg.muted">
<Upload />
</Icon>
<FileUpload.DropzoneContent>
<Box textStyle="p2" fontWeight={600}>
Drag and drop here to upload
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
</Box>
<Box textStyle="p2" color="neutral.800">
.png, .jpg up to 5MB
Comment thread
Juwang110 marked this conversation as resolved.
</Box>
</FileUpload.DropzoneContent>
</FileUpload.Dropzone>
<FileUpload.List clearable />
</FileUpload.Root>
</Field.Root>

<Flex justifyContent="flex-end" mt={4} gap={2}>
<Button
onClick={onClose}
bg={'white'}
color={'black'}
borderColor="neutral.100"
>
Cancel
</Button>

<Button
onClick={handleSubmit}
bg={isFormValid ? '#213C4A' : 'neutral.400'}
Comment thread
Juwang110 marked this conversation as resolved.
Outdated
color={'white'}
disabled={!isFormValid}
>
Continue
</Button>
</Flex>
</Box>
</Dialog.Body>
<Dialog.CloseTrigger asChild>
<CloseButton size="lg" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
);
};

export default OrderReceivedActionModal;
7 changes: 7 additions & 0 deletions apps/frontend/src/containers/homepage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ const Homepage: React.FC = () => {
</RouterLink>
</Link>
</ListItem>
<ListItem textAlign="center">
<Link asChild color="teal.500">
<RouterLink to="/pantry-order-management">
Pantry Order Management
</RouterLink>
</Link>
</ListItem>
</List.Root>
</Box>

Expand Down
Loading