diff --git a/apps/frontend/src/components/floatingAlert.tsx b/apps/frontend/src/components/floatingAlert.tsx
new file mode 100644
index 00000000..b6f6a755
--- /dev/null
+++ b/apps/frontend/src/components/floatingAlert.tsx
@@ -0,0 +1,56 @@
+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 (
+
+
+
+ {message}
+
+
+ );
+}
diff --git a/apps/frontend/src/components/forms/donationDetailsModal.tsx b/apps/frontend/src/components/forms/donationDetailsModal.tsx
index 80b8d15c..5689ea60 100644
--- a/apps/frontend/src/components/forms/donationDetailsModal.tsx
+++ b/apps/frontend/src/components/forms/donationDetailsModal.tsx
@@ -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;
@@ -25,6 +26,8 @@ const DonationDetailsModal: React.FC = ({
const [loadedDonation, setLoadedDonation] = useState();
const [items, setItems] = useState([]);
+ const [alertMessage, setAlertMessage] = useState('');
+
const donationId = donation?.donationId; // adjust if your ID field is different
useEffect(() => {
@@ -40,7 +43,7 @@ const DonationDetailsModal: React.FC = ({
setLoadedDonation(donationData);
setItems(itemsData);
} catch (err) {
- alert('Error fetching donation details: ' + err);
+ setAlertMessage('Error fetching donation details: ' + err);
}
};
@@ -64,6 +67,9 @@ const DonationDetailsModal: React.FC = ({
scrollBehavior="inside"
>
+ {alertMessage && (
+
+ )}
diff --git a/apps/frontend/src/components/forms/orderDetailsModal.tsx b/apps/frontend/src/components/forms/orderDetailsModal.tsx
index 672fefe0..932196b5 100644
--- a/apps/frontend/src/components/forms/orderDetailsModal.tsx
+++ b/apps/frontend/src/components/forms/orderDetailsModal.tsx
@@ -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;
@@ -25,6 +26,8 @@ const OrderDetailsModal: React.FC = ({
}) => {
const [foodRequest, setFoodRequest] = useState(null);
+ const [alertMessage, setAlertMessage] = useState('');
+
useEffect(() => {
if (isOpen) {
const fetchData = async () => {
@@ -34,7 +37,7 @@ const OrderDetailsModal: React.FC = ({
);
setFoodRequest(foodRequestData);
} catch (error) {
- alert('Error fetching food request details:' + error);
+ setAlertMessage('Error fetching food request details:' + error);
}
};
@@ -51,6 +54,9 @@ const OrderDetailsModal: React.FC = ({
}}
closeOnInteractOutside
>
+ {alertMessage && (
+
+ )}
diff --git a/apps/frontend/src/components/forms/requestFormModal.tsx b/apps/frontend/src/components/forms/requestFormModal.tsx
index f54e625e..21278c3a 100644
--- a/apps/frontend/src/components/forms/requestFormModal.tsx
+++ b/apps/frontend/src/components/forms/requestFormModal.tsx
@@ -14,6 +14,7 @@ import {
import { Form, ActionFunction, ActionFunctionArgs } from 'react-router-dom';
import { FoodRequest, FoodTypes, RequestSize } from '../../types/types';
import { ChevronDownIcon } from 'lucide-react';
+import { FloatingAlert } from '@components/floatingAlert';
interface FoodRequestFormModalProps {
previousRequest?: FoodRequest;
@@ -32,6 +33,8 @@ const FoodRequestFormModal: React.FC = ({
const [requestedSize, setRequestedSize] = useState('');
const [additionalNotes, setAdditionalNotes] = useState('');
+ const [alertMessage, setAlertMessage] = useState('');
+
const isFormValid = requestedSize !== '' && selectedItems.length > 0;
useEffect(() => {
@@ -54,6 +57,9 @@ const FoodRequestFormModal: React.FC = ({
}}
closeOnInteractOutside
>
+ {alertMessage && (
+
+ )}
@@ -81,11 +87,11 @@ const FoodRequestFormModal: React.FC = ({
onSubmit={(e) => {
if (selectedItems.length === 0) {
e.preventDefault();
- alert('Please select at least one food type');
+ setAlertMessage('Please select at least one food type');
}
if (requestedSize === '') {
e.preventDefault();
- alert('Please select a requested size.');
+ setAlertMessage('Please select a requested size.');
}
}}
>
@@ -279,7 +285,7 @@ const FoodRequestFormModal: React.FC = ({
if (words.length <= 250) {
setAdditionalNotes(e.target.value);
} else {
- alert('Exceeded word limit');
+ setAlertMessage('Exceeded word limit');
}
}}
/>
diff --git a/apps/frontend/src/containers/FormRequests.tsx b/apps/frontend/src/containers/FormRequests.tsx
index 8d5b2246..79da4dc4 100644
--- a/apps/frontend/src/containers/FormRequests.tsx
+++ b/apps/frontend/src/containers/FormRequests.tsx
@@ -20,6 +20,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';
const FormRequests: React.FC = () => {
const [currentPage, setCurrentPage] = useState(1);
@@ -37,6 +38,8 @@ const FormRequests: React.FC = () => {
const [openReadOnlyRequest, setOpenReadOnlyRequest] =
useState(null);
+ const [alertMessage, setAlertMessage] = useState('');
+
const pageSize = 10;
useEffect(() => {
@@ -53,7 +56,7 @@ const FormRequests: React.FC = () => {
setPreviousRequest(sortedData[0]);
}
} catch (error) {
- alert('Error fetching requests: ' + error);
+ setAlertMessage('Error fetching requests: ' + error);
}
}
};
@@ -71,6 +74,9 @@ const FormRequests: React.FC = () => {
Food Request Management
+ {alertMessage && (
+
+ )}