From 561f6fc2654a8c0b1e3f53a0b62d3e8a4d88a29a Mon Sep 17 00:00:00 2001 From: Mary Caserio <114102750+marycaserio@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:22:52 -0600 Subject: [PATCH] feat: add donor email to organization alerts (#33) - add new function to fetch multiple docs in once. --------- Co-authored-by: Elara Liu <40444637+ZL-Asica@users.noreply.github.com> --- src/components/Alerts/OrganizationAlerts.tsx | 44 +++++++++++++++ src/utils/firebase/firebaseUtils.ts | 58 +++++++++++++++++++- src/utils/firebase/index.ts | 2 +- 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/components/Alerts/OrganizationAlerts.tsx b/src/components/Alerts/OrganizationAlerts.tsx index 49d94b4..4e6c503 100644 --- a/src/components/Alerts/OrganizationAlerts.tsx +++ b/src/components/Alerts/OrganizationAlerts.tsx @@ -8,11 +8,47 @@ import { ListItemText, } from '@mui/material'; import dayjs from 'dayjs'; +import { useState, useEffect } from 'react'; import { useEventStore } from '@/stores'; +import { getOrDefaultDocuments } from '@/utils/firebase'; + +const defaultDonorProfile: DonorProfile = { + uid: '', + name: '', + email: '', + profilePic: '', + joinedEvents: [], + createdAt: new Date().toISOString(), + role: 'donor', + providedSupplies: [], + saved: [], +}; + const OrganizationAlerts = () => { const events = useEventStore((store) => store.events); + const [donorEmails, setDonorEmails] = useState>({}); + + useEffect(() => { + const fetchDonorEmails = async () => { + const donorIds = events.map((event) => event.donorId); + const donorProfiles = await getOrDefaultDocuments( + donorIds, + defaultDonorProfile + ); + + const emails: Record = {}; + for (const profile of donorProfiles) { + emails[profile.uid] = profile.email; + } + setDonorEmails(emails); + }; + + if (events.length > 0) { + fetchDonorEmails(); + } + }, [events]); return ( @@ -43,6 +79,14 @@ const OrganizationAlerts = () => { {event.title.split('from')[1].trim() || 'Loading...'}{' '} {/* Display donor name */} + + Donor Email:{' '} + {donorEmails[event.donorId] || 'Loading...'}{' '} + {/* Display donor name */} + ( } }; -export { getOrCreateDocument, updateDocument }; +const getOrDefaultDocuments = async >( + uids: string[], + defaultData: T +): Promise => { + const results: T[] = []; + const BATCH_SIZE = 10; // Firestore `in` query limit + const collectionName = defaultData.role; + + try { + const existingDocs: Record = {}; + + // Split UIDs into batches to respect Firestore's `in` query limit + const batches = []; + for (let i = 0; i < uids.length; i += BATCH_SIZE) { + batches.push(uids.slice(i, i + BATCH_SIZE)); + } + + // Fetch existing documents in batches + for (const batch of batches) { + const docsQuery = query( + collection(db, collectionName), + where('__name__', 'in', batch) + ); + const querySnapshot = await getDocs(docsQuery); + // eslint-disable-next-line unicorn/no-array-for-each + querySnapshot.forEach((docSnap) => { + if (docSnap.exists()) { + existingDocs[docSnap.id] = docSnap.data() as T; + } + }); + } + + // Map UIDs to their corresponding documents or default data + for (const uid of uids) { + results.push(existingDocs[uid] || { ...defaultData, id: uid }); + } + } catch (error) { + console.error( + `Error in getOrDefaultDocuments for ${collectionName}:`, + error + ); + } + + return results; +}; + +export { getOrCreateDocument, updateDocument, getOrDefaultDocuments }; diff --git a/src/utils/firebase/index.ts b/src/utils/firebase/index.ts index e492942..22bd71d 100644 --- a/src/utils/firebase/index.ts +++ b/src/utils/firebase/index.ts @@ -1,4 +1,4 @@ export { loginUser, logoutUser } from './auth'; export { auth, db } from './firebaseConfig'; -export { updateDocument } from './firebaseUtils'; +export { updateDocument, getOrDefaultDocuments } from './firebaseUtils'; export { updateEvent, removeEvent } from './eventsUtils';