Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1697cbe
Fixed branch issues ignoring lint (Chakra components still having wei…
dburkhart07 Oct 8, 2025
3f6f05c
Fixed issues
dburkhart07 Oct 9, 2025
379edb7
Merge conflict final commit
dburkhart07 Nov 19, 2025
7023e8a
Final commit
dburkhart07 Nov 19, 2025
27ba9d9
Merge branch 'main' into ddb/SSF-8-admin-order-management-frontend
amywng Nov 22, 2025
693bed0
Fixed merge conflicts
dburkhart07 Nov 27, 2025
7fe9ca5
Final commit
dburkhart07 Nov 27, 2025
121d373
Fixed frontend changes
dburkhart07 Nov 28, 2025
a89873d
Fixed frontend changes
dburkhart07 Nov 28, 2025
815daab
Merged main into branch
dburkhart07 Dec 4, 2025
4a53a23
Fixed backend
dburkhart07 Dec 4, 2025
21eb829
Fixed backend
dburkhart07 Dec 4, 2025
505836d
Final commit
dburkhart07 Dec 4, 2025
b462dba
Fixed volunteer display
dburkhart07 Dec 4, 2025
906b21b
Final commit
dburkhart07 Dec 5, 2025
a2fec8c
Final commit
dburkhart07 Dec 5, 2025
35951a4
Resolved comments
dburkhart07 Dec 5, 2025
585b809
Styling changes
dburkhart07 Dec 6, 2025
56a9a82
prettier
dburkhart07 Dec 6, 2025
fdd5784
Resolved merge conflicts
dburkhart07 Dec 6, 2025
cb5ce22
Prettier
dburkhart07 Dec 6, 2025
54d4175
Fixed color theme and remove x from the modals
dburkhart07 Dec 6, 2025
4eff2ee
Final commit
dburkhart07 Dec 6, 2025
b594158
prettier
dburkhart07 Dec 6, 2025
ae13e1f
Added search feature
dburkhart07 Dec 6, 2025
8ca82ec
prettier
dburkhart07 Dec 6, 2025
7991740
Added modal similar to request form modal
dburkhart07 Dec 6, 2025
ecad35e
prettier
dburkhart07 Dec 6, 2025
430c293
More comments resolved
dburkhart07 Dec 7, 2025
a570951
prettier
dburkhart07 Dec 7, 2025
1cc1d48
Fixed modal styligs
dburkhart07 Dec 7, 2025
eb144ae
Resolved comments
dburkhart07 Dec 7, 2025
577b6aa
prettier
dburkhart07 Dec 8, 2025
039e240
Resolved merge conflicts
dburkhart07 Dec 8, 2025
71bade1
Merged main in
dburkhart07 Dec 10, 2025
8fc17d5
prettier
dburkhart07 Dec 10, 2025
c89fd1b
Added proper filtering and sorting, assignee coloring, and fixed type…
dburkhart07 Jan 11, 2026
8ddbe8d
prettier
dburkhart07 Jan 11, 2026
382574c
Addressed changes
dburkhart07 Jan 12, 2026
b715cae
Merged main into branch
dburkhart07 Jan 12, 2026
4da3eb6
Final commit
dburkhart07 Jan 12, 2026
81555d9
Removed useEffects for page updating
dburkhart07 Jan 14, 2026
0087fb4
prettier
dburkhart07 Jan 14, 2026
8e77adc
Fixed yarn.lock
dburkhart07 Jan 15, 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
12 changes: 6 additions & 6 deletions apps/backend/src/orders/order.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { Order } from './order.entity';
import { Pantry } from '../pantries/pantries.entity';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { FoodRequest } from '../foodRequests/request.entity';
import { Donation } from '../donations/donations.entity';
import { AllocationsService } from '../allocations/allocations.service';
import { OrderStatus } from './types';

Expand All @@ -24,8 +23,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 orders where the status is pending and the pantry name is either Test Pantry or Test Pantry 2
@Get('/')
async getAllOrders(
@Query('status') status?: string,
Expand All @@ -47,21 +47,21 @@ export class OrdersController {
return this.ordersService.getPastOrders();
}

@Get(':orderId/pantry')
@Get('/:orderId/pantry')
async getPantryFromOrder(
@Param('orderId', ParseIntPipe) orderId: number,
): Promise<Pantry> {
return this.ordersService.findOrderPantry(orderId);
}

@Get(':orderId/request')
@Get('/:orderId/request')
async getRequestFromOrder(
@Param('orderId', ParseIntPipe) orderId: number,
): Promise<FoodRequest> {
return this.ordersService.findOrderFoodRequest(orderId);
}

@Get(':orderId/manufacturer')
@Get('/:orderId/manufacturer')
async getManufacturerFromOrder(
@Param('orderId', ParseIntPipe) orderId: number,
): Promise<FoodManufacturer> {
Expand All @@ -82,7 +82,7 @@ export class OrdersController {
return this.ordersService.findOrderByRequest(requestId);
}

@Get(':orderId/allocations')
@Get('/:orderId/allocations')
async getAllAllocationsByOrder(
@Param('orderId', ParseIntPipe) orderId: number,
) {
Expand Down
4 changes: 4 additions & 0 deletions apps/backend/src/orders/order.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ export class OrdersService {
const qb = this.repo
.createQueryBuilder('order')
.leftJoinAndSelect('order.pantry', 'pantry')
.leftJoinAndSelect('pantry.volunteers', 'volunteers')
.select([
'order.orderId',
'order.status',
'order.createdAt',
'order.shippedAt',
'order.deliveredAt',
'pantry.pantryName',
'volunteers.id',
'volunteers.firstName',
'volunteers.lastName',
]);

if (filters?.status) {
Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/src/api/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
CreateFoodRequestBody,
Pantry,
PantryApplicationDto,
OrderSummary,
UserDto,
} from 'types/types';

Expand Down Expand Up @@ -171,7 +172,7 @@ export class ApiClient {
.then((response) => response.data);
}

public async getAllOrders(): Promise<Order[]> {
public async getAllOrders(): Promise<OrderSummary[]> {
return this.axiosInstance
.get('/api/orders/')
.then((response) => response.data);
Expand Down
5 changes: 5 additions & 0 deletions apps/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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([
{
Expand Down Expand Up @@ -97,6 +98,10 @@ const router = createBrowserRouter([
path: '/admin-donation',
element: <AdminDonation />,
},
{
path: '/admin-order-management',
element: <AdminOrderManagement />,
},
{
path: '/volunteer-management',
element: <VolunteerManagement />,
Expand Down
193 changes: 137 additions & 56 deletions apps/frontend/src/components/forms/addNewVolunteerModal.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,116 @@
import {
Dialog,
Button,
Text,
Flex,
Field,
Input,
CloseButton,
Box
Dialog,
Button,
Text,
Flex,
Field,
Input,
CloseButton,
Box,
} from '@chakra-ui/react';
import { useState } from 'react';
import { Role, UserDto } from "../../types/types";
import { Role, UserDto } from '../../types/types';
import ApiClient from '@api/apiClient';
import { USPhoneInput } from './usPhoneInput';
import { PlusIcon } from 'lucide-react';

interface NewVolunteerModalProps {
onSubmitSuccess?: () => void;
onSubmitFail?: () => void;
onSubmitSuccess?: () => void;
onSubmitFail?: () => void;
}

const NewVolunteerModal: React.FC<NewVolunteerModalProps> = ({ onSubmitSuccess, onSubmitFail }) => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const NewVolunteerModal: React.FC<NewVolunteerModalProps> = ({
onSubmitSuccess,
onSubmitFail,
}) => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');

const [isOpen, setIsOpen] = useState(false);

const [error, setError] = useState("");
const [error, setError] = useState('');

const handleSubmit = async () => {
console.log("RAW phone value:", phone);
if (!firstName || !lastName || !email || !phone || phone === "+1") {
setError("Please fill in all fields. *");
console.log('RAW phone value:', phone);
if (!firstName || !lastName || !email || !phone || phone === '+1') {
setError('Please fill in all fields. *');
return;
}

setError("");
setError('');

const newVolunteer: UserDto = {
firstName,
lastName,
email,
phone,
role: Role.VOLUNTEER
role: Role.VOLUNTEER,
};

try {
await ApiClient.postUser(newVolunteer);
if (onSubmitSuccess) onSubmitSuccess();
handleClear();
} catch (error: unknown) {
let hasEmailError = false;
let hasPhoneError = false;

let hasEmailError = false
let hasPhoneError = false

if (typeof error === "object" && error !== null) {
const e = error as { response?: { data?: { message?: string | string[] } } };
if (typeof error === 'object' && error !== null) {
const e = error as {
response?: { data?: { message?: string | string[] } };
};
const message = e.response?.data?.message;

hasEmailError =
Array.isArray(message) &&
message.some((msg) => typeof msg === "string" && msg.toLowerCase().includes("email"));
message.some(
(msg) =>
typeof msg === 'string' && msg.toLowerCase().includes('email'),
);

hasPhoneError =
Array.isArray(message) &&
message.some((msg) => typeof msg === "string" && msg.toLowerCase().includes("phone"));
message.some(
(msg) =>
typeof msg === 'string' && msg.toLowerCase().includes('phone'),
);
}

if (hasEmailError) {
setError("Please specify a valid email. *")
setError('Please specify a valid email. *');
} else if (hasPhoneError) {
setError("Please specify a valid phone number. *")
setError('Please specify a valid phone number. *');
} else {
if (onSubmitFail) onSubmitFail();
handleClear();
}
}
}
};

const handleClear = () => {
setFirstName("");
setLastName("");
setEmail("");
setPhone("");
setError("");
setFirstName('');
setLastName('');
setEmail('');
setPhone('');
setError('');
setIsOpen(false);
};

return (
<Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
<Dialog.Trigger asChild>
<Button pl={3} borderColor="neutral.200" variant="outline" color="neutral.600" fontFamily="ibm" fontWeight="semibold" fontSize="14px" gap={1}>
<Button
pl={3}
borderColor="neutral.200"
variant="outline"
color="neutral.600"
fontFamily="ibm"
fontWeight="semibold"
fontSize="14px"
gap={1}
>
<Box as={PlusIcon} boxSize="17px" strokeWidth={2.5} />
Add
</Button>
Expand All @@ -100,31 +119,76 @@ const NewVolunteerModal: React.FC<NewVolunteerModalProps> = ({ onSubmitSuccess,
<Dialog.Positioner alignItems="center">
<Dialog.Content maxW="40em" mt="-8">
<Dialog.Header pb={1}>
<Dialog.Title fontSize="18px" fontWeight={600} fontFamily="Inter" color="#000">
<Dialog.Title
fontSize="18px"
fontWeight={600}
fontFamily="Inter"
color="#000"
>
Add New Volunteer
</Dialog.Title>
<CloseButton onClick={() => setIsOpen(false)} size="md" position="absolute" top={3} right={3}/>
<CloseButton
onClick={() => setIsOpen(false)}
size="md"
position="absolute"
top={3}
right={3}
/>
</Dialog.Header>
<Dialog.Body color="neutral.800" fontWeight={600} textStyle="p2">
<Text mb="1.5em" color="#52525B" fontWeight={400}>
Complete all information in the form to register a new volunteer.
</Text>
<Flex gap={8} justifyContent="flex-start" my={4}>
<Field.Root>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>First Name</Field.Label>
<Input color="neutral.700" textStyle="p2" fontWeight={400} value={firstName} onChange={(e) => setFirstName(e.target.value)}/>
<Field.Label
textStyle="p2"
color="neutral.800"
fontWeight={600}
>
First Name
</Field.Label>
<Input
color="neutral.700"
textStyle="p2"
fontWeight={400}
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
</Field.Root>
<Field.Root>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>Last Name</Field.Label>
<Input color="neutral.700" textStyle="p2" fontWeight={400} value={lastName} onChange={(e) => setLastName(e.target.value)}/>
<Field.Label
textStyle="p2"
color="neutral.800"
fontWeight={600}
>
Last Name
</Field.Label>
<Input
color="neutral.700"
textStyle="p2"
fontWeight={400}
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</Field.Root>
</Flex>
<Field.Root>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>Email</Field.Label>
<Input color="neutral.700" textStyle="p2" fontWeight={400} value={email} onChange={(e) => setEmail(e.target.value)}/>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>
Email
</Field.Label>
<Input
color="neutral.700"
textStyle="p2"
fontWeight={400}
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</Field.Root>
<Field.Root my={4}>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>Phone Number</Field.Label>
<Field.Label textStyle="p2" color="neutral.800" fontWeight={600}>
Phone Number
</Field.Label>
<USPhoneInput
value={phone}
onChange={setPhone}
Expand All @@ -136,13 +200,35 @@ const NewVolunteerModal: React.FC<NewVolunteerModalProps> = ({ onSubmitSuccess,
/>
</Field.Root>
{error && (
<Text color="red" mb={3} fontWeight={400} fontSize="12px" fontFamily="Inter">
<Text
color="red"
mb={3}
fontWeight={400}
fontSize="12px"
fontFamily="Inter"
>
{error}
</Text>
)}
<Flex justifyContent="flex-end" mt={10} gap={2.5}>
<Button textStyle="p2" fontWeight={600} color="neutral.800" variant='outline' onClick={handleClear}>Cancel</Button>
<Button textStyle="p2" fontWeight={600} bg={'#213C4A'} color={'white'} onClick={handleSubmit}>Submit</Button>
<Button
textStyle="p2"
fontWeight={600}
color="neutral.800"
variant="outline"
onClick={handleClear}
>
Cancel
</Button>
<Button
textStyle="p2"
fontWeight={600}
bg={'#213C4A'}
color={'white'}
onClick={handleSubmit}
>
Submit
</Button>
</Flex>
</Dialog.Body>
</Dialog.Content>
Expand All @@ -151,9 +237,4 @@ const NewVolunteerModal: React.FC<NewVolunteerModalProps> = ({ onSubmitSuccess,
);
};






export default NewVolunteerModal;
export default NewVolunteerModal;
Loading
Loading