refactor: memoize real-time RSVP update handler for improved stability and performance.
This commit is contained in:
@@ -693,9 +693,8 @@ export function AdminDashboard({
|
||||
});
|
||||
}, [magicLinkDialog, toast]);
|
||||
|
||||
// Real-time updates
|
||||
useAdminRealtime({
|
||||
onRSVPUpdate: (event) => {
|
||||
// Memoized RSVP update handler for stable reference in real-time subscription
|
||||
const handleRSVPUpdate = useCallback((event: any) => {
|
||||
if (event.action === "create" || event.action === "update") {
|
||||
// Refresh both RSVP data and guest list to sync status
|
||||
Promise.all([
|
||||
@@ -721,7 +720,28 @@ export function AdminDashboard({
|
||||
console.warn('[AdminDashboard] Failed to refresh RSVP data:', error);
|
||||
}),
|
||||
// Refresh guest list to sync RSVP status - CRITICAL for Master Guest List sync
|
||||
refreshGuestList(),
|
||||
fetch(`/api/admin/guests?includeCheckIn=true&page=${currentPage}&limit=${pageSize}`, {
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(guestsData => {
|
||||
if (guestsData.pagination) {
|
||||
setGuests(guestsData.guests || []);
|
||||
setTotalGuests(guestsData.pagination.total || 0);
|
||||
setTotalPages(guestsData.pagination.totalPages || 1);
|
||||
} else if (Array.isArray(guestsData)) {
|
||||
setGuests(guestsData);
|
||||
setTotalGuests(guestsData.length);
|
||||
setTotalPages(1);
|
||||
} else if (Array.isArray(guestsData.guests)) {
|
||||
setGuests(guestsData.guests);
|
||||
setTotalGuests(guestsData.pagination?.total || guestsData.guests.length);
|
||||
setTotalPages(guestsData.pagination?.totalPages || 1);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('[AdminDashboard] Failed to refresh guest list:', error);
|
||||
}),
|
||||
]).then(() => {
|
||||
// Only show toast for create actions to avoid spam on updates
|
||||
if (event.action === "create") {
|
||||
@@ -735,15 +755,41 @@ export function AdminDashboard({
|
||||
console.warn('[AdminDashboard] Failed to refresh data after RSVP update:', error);
|
||||
});
|
||||
}
|
||||
},
|
||||
onGuestUpdate: (event) => {
|
||||
}, [currentPage, pageSize, toast]);
|
||||
|
||||
// Memoized guest update handler for stable reference
|
||||
const handleGuestUpdate = useCallback((event: any) => {
|
||||
// Also refresh guest list when guest data is updated directly
|
||||
if (event.action === "update") {
|
||||
refreshGuestList().catch(error => {
|
||||
fetch(`/api/admin/guests?includeCheckIn=true&page=${currentPage}&limit=${pageSize}`, {
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(guestsData => {
|
||||
if (guestsData.pagination) {
|
||||
setGuests(guestsData.guests || []);
|
||||
setTotalGuests(guestsData.pagination.total || 0);
|
||||
setTotalPages(guestsData.pagination.totalPages || 1);
|
||||
} else if (Array.isArray(guestsData)) {
|
||||
setGuests(guestsData);
|
||||
setTotalGuests(guestsData.length);
|
||||
setTotalPages(1);
|
||||
} else if (Array.isArray(guestsData.guests)) {
|
||||
setGuests(guestsData.guests);
|
||||
setTotalGuests(guestsData.pagination?.total || guestsData.guests.length);
|
||||
setTotalPages(guestsData.pagination?.totalPages || 1);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.warn('[AdminDashboard] Failed to refresh guest list after guest update:', error);
|
||||
});
|
||||
}
|
||||
},
|
||||
}, [currentPage, pageSize]);
|
||||
|
||||
// Real-time updates with memoized handlers
|
||||
useAdminRealtime({
|
||||
onRSVPUpdate: handleRSVPUpdate,
|
||||
onGuestUpdate: handleGuestUpdate,
|
||||
onCheckinUpdate: (event) => {
|
||||
if (event.action === "create") {
|
||||
const guestId = event.data?.guestId as string | undefined;
|
||||
@@ -1818,8 +1864,8 @@ export function AdminDashboard({
|
||||
setNotifications(prev => prev.filter(n => n.id !== id));
|
||||
};
|
||||
|
||||
// Helper function to refresh guest list
|
||||
const refreshGuestList = async (page = currentPage) => {
|
||||
// Helper function to refresh guest list - memoized for stable reference in real-time handlers
|
||||
const refreshGuestList = useCallback(async (page = currentPage) => {
|
||||
try {
|
||||
const guestsRes = await fetch(`/api/admin/guests?includeCheckIn=true&page=${page}&limit=${pageSize}`, {
|
||||
credentials: 'include'
|
||||
@@ -1845,7 +1891,7 @@ export function AdminDashboard({
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh guest list:', error);
|
||||
}
|
||||
};
|
||||
}, [currentPage, pageSize]);
|
||||
|
||||
// Handle sending guest invitation
|
||||
const handleSendInvite = async () => {
|
||||
@@ -3929,8 +3975,7 @@ export function AdminDashboard({
|
||||
<p className="text-xs text-wedding-moss/70">
|
||||
by {photo.uploadedBy} • {photo.time}
|
||||
</p>
|
||||
<span className={`text-xs px-2 py-1 rounded-full ${
|
||||
photo.approved ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||
<span className={`text-xs px-2 py-1 rounded-full ${photo.approved ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||
}`}>
|
||||
{photo.approved ? 'Approved' : 'Pending'}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user