Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 57 additions & 0 deletions apps/frontend/src/components/floatingAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Alert } from '@chakra-ui/react';
import { useEffect, useState } from 'react';

type FloatingAlertProps = {
message?: string | null;
status?: 'info' | 'error';
timeout?: number;
};

export function FloatingAlert({
message,
status,
timeout,
}: FloatingAlertProps) {
const [visible, setVisible] = useState(!!message);

useEffect(() => {
if (!message) {
setVisible(false);
return;
}

setVisible(true);

if (!timeout) return;

const timer = setTimeout(() => {
setVisible(false);
}, timeout);

return () => clearTimeout(timer);
}, [message, timeout]);

if (!message || !visible) return null;

return (
<Alert.Root
color={status === 'info' ? 'neutral.800' : 'red'}
status="info"
bg="white"
variant="subtle"
boxShadow="lg"
position="fixed"
zIndex="toast"
top="12px"
right="12px"
w="fit-content"
maxW="400px"
p={2}
>
<Alert.Indicator />
<Alert.Title textStyle="p2" fontWeight={500}>
{message}
</Alert.Title>
</Alert.Root>
);
}
8 changes: 7 additions & 1 deletion apps/frontend/src/components/forms/donationDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import ApiClient from '@api/apiClient';
import { Donation, DonationItem, FoodType } from 'types/types';
import { formatDate } from '@utils/utils';
import { FloatingAlert } from '@components/floatingAlert';

interface DonationDetailsModalProps {
donation: Donation;
Expand All @@ -25,6 +26,8 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
const [loadedDonation, setLoadedDonation] = useState<Donation>();
const [items, setItems] = useState<DonationItem[]>([]);

const [alertMessage, setAlertMessage] = useState<string>('');

const donationId = donation.donationId;

useEffect(() => {
Expand All @@ -40,7 +43,7 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
setLoadedDonation(donationData);
setItems(itemsData);
} catch (err) {
alert('Error fetching donation details: ' + err);
setAlertMessage('Error fetching donation details: ' + err);
}
};

Expand All @@ -63,6 +66,9 @@ const DonationDetailsModal: React.FC<DonationDetailsModalProps> = ({
closeOnInteractOutside
scrollBehavior="inside"
>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<Portal>
<Dialog.Backdrop bg="blackAlpha.300" />

Expand Down
8 changes: 7 additions & 1 deletion apps/frontend/src/components/forms/orderDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import ApiClient from '@api/apiClient';
import { FoodRequest, OrderSummary } from 'types/types';
import { formatDate } from '@utils/utils';
import { FloatingAlert } from '@components/floatingAlert';

interface OrderDetailsModalProps {
order: OrderSummary;
Expand All @@ -25,6 +26,8 @@ const OrderDetailsModal: React.FC<OrderDetailsModalProps> = ({
}) => {
const [foodRequest, setFoodRequest] = useState<FoodRequest | null>(null);

const [alertMessage, setAlertMessage] = useState<string>('');

useEffect(() => {
if (isOpen) {
const fetchData = async () => {
Expand All @@ -34,7 +37,7 @@ const OrderDetailsModal: React.FC<OrderDetailsModalProps> = ({
);
setFoodRequest(foodRequestData);
} catch (error) {
alert('Error fetching food request details:' + error);
setAlertMessage('Error fetching food request details:' + error);
}
};

Expand All @@ -51,6 +54,9 @@ const OrderDetailsModal: React.FC<OrderDetailsModalProps> = ({
}}
closeOnInteractOutside
>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content maxW={650}>
Expand Down
7 changes: 3 additions & 4 deletions apps/frontend/src/components/forms/requestFormModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
RequestSize,
} from '../../types/types';
import { ChevronDownIcon } from 'lucide-react';
import { FloatingAlert } from '@components/floatingAlert';
import apiClient from '@api/apiClient';

interface FoodRequestFormModalProps {
Expand Down Expand Up @@ -89,9 +90,7 @@ const FoodRequestFormModal: React.FC<FoodRequestFormModalProps> = ({
closeOnInteractOutside
>
{alertMessage && (
// TODO: add Justin's alert component/uncomment below out and remove text component
// <FloatingAlert message={alertMessage} status="error" timeout={6000} />
<Text>{alertMessage}</Text>
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<Dialog.Backdrop />
<Dialog.Positioner>
Expand Down Expand Up @@ -293,7 +292,7 @@ const FoodRequestFormModal: React.FC<FoodRequestFormModalProps> = ({
if (words.length <= 250) {
setAdditionalNotes(e.target.value);
} else {
alert('Exceeded word limit');
setAlertMessage('Exceeded word limit');
}
}}
/>
Expand Down
17 changes: 10 additions & 7 deletions apps/frontend/src/components/forms/resetPasswordModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import {
Field,
} from '@chakra-ui/react';
import { resetPassword, confirmResetPassword } from 'aws-amplify/auth';
import { FloatingAlert } from '@components/floatingAlert';

const ResetPasswordModal: React.FC = () => {
const [email, setEmail] = useState<string>('');
const [code, setCode] = useState<string>('');
const [step, setStep] = useState<'reset' | 'new'>('reset');
const [password, setPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const [alertMessage, setAlertMessage] = useState<string>('');

const navigate = useNavigate();

Expand All @@ -25,27 +27,26 @@ const ResetPasswordModal: React.FC = () => {
await resetPassword({ username: email });
setStep('new');
} catch (error) {
alert(error || 'Failed to send verification code');
setAlertMessage('Failed to send verification code: ' + error);
}
};

const handleResendCode = async () => {
try {
await resetPassword({ username: email });
alert('Successfully sent verification code');
} catch (error) {
alert(error || 'Failed to send verification code');
setAlertMessage('Failed to send verification code: ' + error);
}
};

const handleResetPassword = async () => {
if (password !== confirmPassword) {
alert('Passwords need to match');
setAlertMessage('Passwords need to match');
return;
}

if (password.length < 8) {
alert('Password needs to be at least 8 characters');
setAlertMessage('Password needs to be at least 8 characters');
return;
}

Expand All @@ -55,10 +56,9 @@ const ResetPasswordModal: React.FC = () => {
confirmationCode: code,
newPassword: password,
});
alert('Password reset successful!');
navigate('/login');
} catch (error) {
alert(error || 'Failed to set new password');
setAlertMessage('Failed to set new password: ' + error);
}
};

Expand Down Expand Up @@ -92,6 +92,9 @@ const ResetPasswordModal: React.FC = () => {
borderRadius="xl"
boxShadow="xl"
>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<VStack gap={5} align="stretch">
<Box mb={4}>
<Text textStyle="h1">
Expand Down
8 changes: 7 additions & 1 deletion apps/frontend/src/containers/adminDonation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Donation } from 'types/types';
import DonationDetailsModal from '@components/forms/donationDetailsModal';
import ApiClient from '@api/apiClient';
import { formatDate } from '@utils/utils';
import { FloatingAlert } from '@components/floatingAlert';

const AdminDonation: React.FC = () => {
const [donations, setDonations] = useState<Donation[]>([]);
Expand All @@ -28,13 +29,15 @@ const AdminDonation: React.FC = () => {
null,
);

const [alertMessage, setAlertMessage] = useState<string>('');

useEffect(() => {
const fetchDonations = async () => {
try {
const data = await ApiClient.getAllDonations();
setDonations(data);
} catch (error) {
alert('Error fetching donations: ' + error);
setAlertMessage('Error fetching donations: ' + error);
}
};
fetchDonations();
Expand Down Expand Up @@ -99,6 +102,9 @@ const AdminDonation: React.FC = () => {
<Heading textStyle="h1" color="gray.600" mb={6}>
Donation Management
</Heading>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<Box display="flex" gap={2} mb={6} fontFamily="'Inter', sans-serif">
<Box position="relative">
<Button
Expand Down
9 changes: 8 additions & 1 deletion apps/frontend/src/containers/adminOrderManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { capitalize, formatDate } from '@utils/utils';
import ApiClient from '@api/apiClient';
import { OrderStatus, OrderSummary } from '../types/types';
import OrderDetailsModal from '@components/forms/orderDetailsModal';
import { FloatingAlert } from '@components/floatingAlert';

// Extending the OrderSummary type to include assignee color for display
type OrderWithColor = OrderSummary & { assigneeColor?: string };
Expand All @@ -50,6 +51,8 @@ const AdminOrderManagement: React.FC = () => {
},
);

const [alertMessage, setAlertMessage] = useState<string>('');

// State to hold filter state per status
type FilterState = {
selectedPantries: string[];
Expand Down Expand Up @@ -143,7 +146,7 @@ const AdminOrderManagement: React.FC = () => {
};
setCurrentPages(initialPages);
} catch (error) {
alert('Error fetching orders: ' + error);
setAlertMessage('Error fetching orders: ' + error);
}
};

Expand All @@ -168,6 +171,10 @@ const AdminOrderManagement: React.FC = () => {
Order Management
</Heading>

{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}

{STATUS_ORDER.map((status) => {
const allOrders = statusOrders[status] || [];
const filterState = filterStates[status];
Expand Down
10 changes: 8 additions & 2 deletions apps/frontend/src/containers/formRequests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { OrderStatus, FoodRequest } from '../types/types';
import RequestDetailsModal from '@components/forms/requestDetailsModal';
import { formatDate } from '@utils/utils';
import ApiClient from '@api/apiClient';
import { FloatingAlert } from '@components/floatingAlert';
import { useAuthenticator } from '@aws-amplify/ui-react';

const FormRequests: React.FC = () => {
Expand All @@ -36,6 +37,8 @@ const FormRequests: React.FC = () => {
const [openReadOnlyRequest, setOpenReadOnlyRequest] =
useState<FoodRequest | null>(null);

const [alertMessage, setAlertMessage] = useState<string>('');

const pageSize = 10;

const fetchRequests = useCallback(async () => {
Expand All @@ -52,10 +55,10 @@ const FormRequests: React.FC = () => {
setPreviousRequest(sortedData[0]);
}
} catch (error) {
console.log(error);
setAlertMessage('Error fetching requests: ' + error);
}
} else {
alert('No pantry associated with this account.');
setAlertMessage('No pantry associated with this account.');
}
}, []);

Expand All @@ -74,6 +77,9 @@ const FormRequests: React.FC = () => {
<Text textStyle="h1" color="#515151">
Food Request Management
</Text>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<HStack gap={3} my={5}>
<Button
fontFamily="ibm"
Expand Down
7 changes: 6 additions & 1 deletion apps/frontend/src/containers/loginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import {
} from '@chakra-ui/react';
import loginBackground from '../assets/login_background.png';
import { Eye, EyeOff } from 'lucide-react';
import { FloatingAlert } from '@components/floatingAlert';

const LoginPage: React.FC = () => {
const [email, setEmail] = useState<string>('');
const [password, setPassword] = useState<string>('');
const [showPassword, setShowPassword] = useState(false);
const [alertMessage, setAlertMessage] = useState<string>('');
const navigate = useNavigate();
const location = useLocation();

Expand All @@ -29,7 +31,7 @@ const LoginPage: React.FC = () => {
await signIn({ username: email, password });
navigate(from, { replace: true });
} catch (error) {
alert(error || 'Login failed');
setAlertMessage('Login failed: ' + error);
}
};

Expand Down Expand Up @@ -58,6 +60,9 @@ const LoginPage: React.FC = () => {
alignItems="center"
justifyContent="center"
>
{alertMessage && (
<FloatingAlert message={alertMessage} status="error" timeout={6000} />
)}
<Box
maxW="500px"
w="full"
Expand Down
Loading