Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
501e100
login UI cleaned
Yurika-Kan Jul 25, 2026
db39afa
Homepage UI
Yurika-Kan Jul 30, 2026
a22c5b6
Merge remote-tracking branch 'origin/main' into yk/admin-bugbash
Yurika-Kan Aug 10, 2026
186714d
UI flicker on page load/refresh
Yurika-Kan Aug 10, 2026
ddeb91c
bad deep-link id fix
Yurika-Kan Aug 10, 2026
52174c9
donation stats pagination
Yurika-Kan Aug 10, 2026
f64cffa
fix API failure on Application Review renders No Applications success…
Yurika-Kan Aug 12, 2026
bfb1d7e
better user promotion aws language
Yurika-Kan Aug 12, 2026
56e7f6b
fix Pagination arrows on Approve Food Manufacturers
Yurika-Kan Aug 12, 2026
3e4e762
fix Pantry assignee cell renders blank when every assigned volunteer …
Yurika-Kan Aug 12, 2026
711c863
User Management lists admins but has no Role label
Yurika-Kan Aug 12, 2026
104ee89
Filtering to zero results shows a bare table or wrong copy
Yurika-Kan Aug 12, 2026
77538f5
Order Management table is cut off on narrow windows with no horizonta…
Yurika-Kan Aug 12, 2026
7fc7298
remove all pages from navbars
Yurika-Kan Aug 12, 2026
ea2efd2
focus trap errors
Yurika-Kan Aug 12, 2026
518b29a
Admin order table does not refresh after editing allocations
Yurika-Kan Aug 12, 2026
d6561b2
cleanup & phone number wording
Yurika-Kan Aug 13, 2026
d21c358
fix: derive donationId from displayDonation, not donation
Yurika-Kan Aug 13, 2026
2427faf
fix fontStyle type error
Yurika-Kan Aug 14, 2026
0e61d39
fix(frontend): restore href semantics on pantry details link
Copilot Aug 14, 2026
dc06b91
secondary phone num wording
Yurika-Kan Aug 14, 2026
b3a4771
href > onclick
Yurika-Kan Aug 14, 2026
08ea5e9
phone num wording
Yurika-Kan Aug 14, 2026
0b21aa3
pagination ultimate form
Yurika-Kan Aug 14, 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
16 changes: 13 additions & 3 deletions apps/backend/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ConflictException,
HttpException,
Injectable,
InternalServerErrorException,
Logger,
Expand Down Expand Up @@ -75,10 +76,18 @@ export class AuthService {

return sub ?? '';
} catch (error) {
if (error instanceof Error && error.name == 'UsernameExistsException') {
if (error instanceof HttpException) {
throw error;
} else if (
error instanceof Error &&
error.name == 'UsernameExistsException'
) {
throw new ConflictException('A user with this email already exists');
} else {
throw new InternalServerErrorException('Failed to create user');
const reason = error instanceof Error ? error.message : String(error);
throw new InternalServerErrorException(
`Failed to create user: ${reason}`,
);
}
}
}
Expand All @@ -97,8 +106,9 @@ export class AuthService {
`Failed to add user ${username} to group ${groupName}`,
error,
);
const reason = error instanceof Error ? error.message : String(error);
throw new InternalServerErrorException(
`Failed to add user to group ${groupName}`,
`Failed to add user to group ${groupName}: ${reason}`,
);
}
}
Expand Down
3 changes: 1 addition & 2 deletions apps/backend/src/auth/dtos/sign-up.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ export class SignUpDto {
@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'phone must be a valid phone number (make sure all the digits are correct)',
message: 'Phone must be a valid US phone number.',
})
phone!: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export class FoodManufacturerApplicationDto {
@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'contactPhone must be a valid phone number (make sure all the digits are correct)',
message: 'Phone must be a valid US phone number.',
})
contactPhone!: string;

Expand All @@ -67,8 +66,7 @@ export class FoodManufacturerApplicationDto {
@IsOptional()
@IsString()
@IsPhoneNumber('US', {
message:
'secondaryContactPhone must be a valid phone number (make sure all the digits are correct)',
message: 'Secondary phone must be a valid US phone number.',
})
Comment thread
Yurika-Kan marked this conversation as resolved.
@IsNotEmpty()
secondaryContactPhone?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ export class UpdateFoodManufacturerApplicationDto {
@IsOptional()
@IsString()
@IsPhoneNumber('US', {
message:
'secondaryContactPhone must be a valid phone number (make sure all the digits are correct)',
message: 'Secondary phone contact must be a valid US phone number.',
})
Comment thread
Yurika-Kan marked this conversation as resolved.
@IsNotEmpty()
secondaryContactPhone?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export class FoodManufacturersController {
type: 'string',
format: 'phone',
example: '(508) 508-6789',
description: 'Must be a valid US phone number',
description: 'Phone must be a valid US phone number',
},
secondaryContactFirstName: {
type: 'string',
Expand All @@ -178,7 +178,7 @@ export class FoodManufacturersController {
type: 'string',
format: 'phone',
example: '(508) 528-6789',
description: 'Must be a valid US phone number',
description: 'Phone must be a valid US phone number',
},
unlistedProductAllergens: {
type: 'array',
Expand Down
6 changes: 2 additions & 4 deletions apps/backend/src/pantries/dtos/pantry-application.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ export class PantryApplicationDto {
@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'contactPhone must be a valid phone number (make sure all the digits are correct)',
message: 'Phone must be a valid US phone number.',
})
contactPhone!: string;

Expand Down Expand Up @@ -74,8 +73,7 @@ export class PantryApplicationDto {
@IsOptional()
@IsString()
@IsPhoneNumber('US', {
message:
'secondaryContactPhone must be a valid phone number (make sure all the digits are correct)',
message: 'Secondary phone must be a valid US phone number.',
})
Comment thread
Yurika-Kan marked this conversation as resolved.
@IsNotEmpty()
secondaryContactPhone?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ export class UpdatePantryApplicationDto {
@IsOptional()
@IsString()
@IsPhoneNumber('US', {
message:
'Secondary contact phone must be a valid phone number (make sure all the digits are correct)',
message: 'Secondary phone must be a valid US phone number.',
})
Comment thread
Yurika-Kan marked this conversation as resolved.
@IsNotEmpty()
secondaryContactPhone?: string;
Expand Down
4 changes: 2 additions & 2 deletions apps/backend/src/pantries/pantries.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export class PantriesController {
type: 'string',
format: 'phone',
example: '(508) 508-6789',
description: 'Must be a valid US phone number',
description: 'Phone must be a valid US phone number',
},
hasEmailContact: {
type: 'boolean',
Expand All @@ -198,7 +198,7 @@ export class PantriesController {
type: 'string',
format: 'phone',
example: '(508) 528-6789',
description: 'Must be a valid US phone number',
description: 'Phone must be a valid US phone number',
},
pantryName: {
type: 'string',
Expand Down
3 changes: 1 addition & 2 deletions apps/backend/src/users/dtos/update-user-info.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ export class UpdateUserInfoDto {
@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'phone must be a valid phone number (make sure all the digits are correct)',
message: 'Phone must be a valid US phone number.',
})
phone?: string;
}
3 changes: 1 addition & 2 deletions apps/backend/src/users/dtos/userSchema.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ export class userSchemaDto {
@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'phone must be a valid phone number (make sure all the digits are correct)',
message: 'Phone must be a valid US phone number.',
})
phone!: string;

Expand Down
Binary file modified apps/frontend/src/assets/login_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 2 additions & 9 deletions apps/frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ const Navbar: React.FC = () => {
ApiClient.getMe()
.then(setCurrentUser)
.catch(() => setCurrentUser(null));
} else {
} else if (authStatus === 'unauthenticated') {
setCurrentUser(null);
}
}, [authStatus]);
Expand Down Expand Up @@ -271,7 +271,6 @@ const Navbar: React.FC = () => {
navigate(ROUTES.LOGIN, { replace: true });
};

// Should be changed once other dashboards are implmented
const ROLE_DASHBOARD_ROUTE: Record<Role, string> = {
[Role.ADMIN]: ROUTES.ADMIN_DASHBOARD,
[Role.FOODMANUFACTURER]: ROUTES.FM_DASHBOARD,
Expand Down Expand Up @@ -330,7 +329,7 @@ const Navbar: React.FC = () => {
overflow="hidden"
style={{ whiteSpace: 'normal', wordBreak: 'break-word' }}
>
{roleLabel ? `${roleLabel} Dashboard` : 'Dashboard'}
{roleLabel ? `${roleLabel}` : 'Profile'}
</Text>
<Text
fontSize="10px"
Expand All @@ -345,12 +344,6 @@ const Navbar: React.FC = () => {
</RouterLink>

<VStack align="stretch" gap={2} flex={1} overflowY="auto">
<NavLink
Comment thread
Yurika-Kan marked this conversation as resolved.
to={ROUTES.HOME}
label="All Pages"
isActive={location.pathname === ROUTES.HOME}
/>

<NavLink
to={ROLE_DASHBOARD_ROUTE[currentUser.role]}
label="Dashboard"
Expand Down
62 changes: 7 additions & 55 deletions apps/frontend/src/components/foodRequestManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@ import {
Button,
Table,
Heading,
Pagination,
IconButton,
VStack,
ButtonGroup,
Checkbox,
Link,
} from '@chakra-ui/react';
import { ArrowDownUp, ChevronRight, ChevronLeft, Funnel } from 'lucide-react';
import { ArrowDownUp, Funnel } from 'lucide-react';
import { capitalize, formatDate } from '@utils/utils';
import { FloatingAlert } from '@components/floatingAlert';
import { FoodRequestStatus, FoodRequestSummaryDto } from '../types/types';
import PageEmptyState from '@components/pageEmptyState';
import { PaginationControl } from '@components/pagination';
import RequestDetailsModal from '@components/forms/requestDetailsModal';
import PantryDeleteRequestActionModal from '@components/forms/pantryDeleteRequestModal';
import VolunteerCloseRequestActionModal from '@components/forms/volunteerCloseRequestModal';
Expand Down Expand Up @@ -131,7 +129,6 @@ const RequestManagement: React.FC<RequestManagementProps> = ({
);

const itemsPerPage = 10;
const totalPages = Math.ceil(filteredRequests.length / itemsPerPage);
const paginatedRequests = filteredRequests.slice(
(currentPage - 1) * itemsPerPage,
currentPage * itemsPerPage,
Expand Down Expand Up @@ -469,59 +466,14 @@ const RequestManagement: React.FC<RequestManagementProps> = ({
</>
)}

{totalPages > 1 && (
<Pagination.Root
<Box mt={12}>
<PaginationControl
count={filteredRequests.length}
pageSize={itemsPerPage}
page={currentPage}
onPageChange={(e: { page: number }) => setCurrentPage(e.page)}
>
<ButtonGroup
display="flex"
justifyContent="center"
alignItems="center"
mt={12}
variant="outline"
size="sm"
gap={4}
>
<Pagination.PrevTrigger asChild>
<IconButton
variant="ghost"
disabled={currentPage === 1}
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
>
<ChevronLeft size={16} />
</IconButton>
</Pagination.PrevTrigger>

<Pagination.Items
render={(page) => (
<IconButton
borderColor={{
base: 'neutral.100',
_selected: 'neutral.600',
}}
>
{page.value}
</IconButton>
)}
/>

<Pagination.NextTrigger asChild>
<IconButton
variant="ghost"
disabled={currentPage === totalPages}
onClick={() =>
setCurrentPage((prev) => Math.min(prev + 1, totalPages))
}
>
<ChevronRight size={16} />
</IconButton>
</Pagination.NextTrigger>
</ButtonGroup>
</Pagination.Root>
)}
onPageChange={setCurrentPage}
/>
</Box>
</Box>
);
};
Expand Down
59 changes: 33 additions & 26 deletions apps/frontend/src/components/forms/donationDetailsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useCallback, useRef } from 'react';
import {
Box,
Text,
Expand Down Expand Up @@ -48,7 +48,11 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({

const [isEditing, setIsEditing] = useState(false);

const donationId = donation?.donationId;
const donationRef = useRef<Donation | null>(donation);
if (donation) donationRef.current = donation;
const displayDonation = donation ?? donationRef.current;

const donationId = displayDonation?.donationId;

const handleCancel = () => {
setIsEditing(false);
Expand Down Expand Up @@ -124,7 +128,7 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
)}
<Dialog.Backdrop bg="blackAlpha.300" />

{donation !== null && (
{displayDonation !== null && (
<Dialog.Positioner>
<Dialog.Content
maxW={isEditing ? '75vw' : 'lg'}
Expand All @@ -140,7 +144,7 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
<Dialog.Title fontSize="lg" fontWeight="600">
Donation #{donationId} Stock
</Dialog.Title>
{donation.status === DonationStatus.AVAILABLE &&
{displayDonation.status === DonationStatus.AVAILABLE &&
!isEditing && (
<>
<EditButton
Expand All @@ -151,9 +155,11 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
)}
</HStack>
<Text fontSize="sm">
{donation.foodManufacturer?.foodManufacturerName}
{displayDonation.foodManufacturer?.foodManufacturerName}
</Text>
<Text fontSize="sm">
{formatDate(displayDonation.dateDonated)}
</Text>
<Text fontSize="sm">{formatDate(donation.dateDonated)}</Text>
</VStack>
</Dialog.Header>

Expand Down Expand Up @@ -226,27 +232,28 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
</VStack>
)}

{!isEditing && donation.recurrence !== RecurrenceEnum.NONE && (
<Box mt={6} color="neutral.800" fontSize="sm">
<Text fontWeight={600} mb={3}>
Donation sets up recurring reminders
</Text>
{!isEditing &&
displayDonation.recurrence !== RecurrenceEnum.NONE && (
<Box mt={6} color="neutral.800" fontSize="sm">
<Text fontWeight={600} mb={3}>
Donation sets up recurring reminders
</Text>

{donation.nextDonationDates &&
donation.nextDonationDates.length > 0 && (
<Box>
<Text fontWeight={600} color="neutral.700" mb={2}>
Upcoming reminder emails
</Text>
<Text color="neutral.700">
{donation.nextDonationDates
.map((date) => formatDate(date))
.join(', ')}
</Text>
</Box>
)}
</Box>
)}
{displayDonation.nextDonationDates &&
displayDonation.nextDonationDates.length > 0 && (
<Box>
<Text fontWeight={600} color="neutral.700" mb={2}>
Upcoming reminder emails
</Text>
<Text color="neutral.700">
{displayDonation.nextDonationDates
.map((date) => formatDate(date))
.join(', ')}
</Text>
</Box>
)}
</Box>
)}
</Dialog.Body>
</Dialog.Content>
</Dialog.Positioner>
Expand Down
Loading
Loading