Pages corrections pages health

This commit is contained in:
alma 2026-01-16 17:12:56 +01:00
parent e23965b0fd
commit d1e34c5081
2 changed files with 132 additions and 98 deletions

View File

@ -40,6 +40,8 @@ export function Email() {
const [accountErrors, setAccountErrors] = useState<Record<string, string>>({}); const [accountErrors, setAccountErrors] = useState<Record<string, string>>({});
const { triggerNotification } = useWidgetNotification(); const { triggerNotification } = useWidgetNotification();
const lastUnreadCountRef = useRef<number>(-1); const lastUnreadCountRef = useRef<number>(-1);
const lastEmailIdsRef = useRef<Set<string>>(new Set());
const isInitializedRef = useRef(false);
// Create a map for quick account lookup by ID (recalculated when accounts change) // Create a map for quick account lookup by ID (recalculated when accounts change)
const accountMap = useMemo(() => { const accountMap = useMemo(() => {
@ -173,64 +175,87 @@ export function Email() {
// Calculate unread count // Calculate unread count
const currentUnreadCount = transformedEmails.filter(e => !e.read).length; const currentUnreadCount = transformedEmails.filter(e => !e.read).length;
const currentEmailIds = new Set(transformedEmails.map(e => e.id));
// Trigger notification if count changed // Detect new emails by comparing IDs (more reliable than count)
if (currentUnreadCount !== lastUnreadCountRef.current) { const newEmailIds = new Set(
const previousCount = lastUnreadCountRef.current; Array.from(currentEmailIds).filter(id => !lastEmailIdsRef.current.has(id))
lastUnreadCountRef.current = currentUnreadCount; );
const hasNewEmails = newEmailIds.size > 0;
// Prepare notification items (unread emails only, max 10) // On first load, just store email IDs without triggering notifications
const notificationItems = transformedEmails if (!isInitializedRef.current) {
.filter(e => !e.read) console.log('[Email Widget] 📧 Initializing - storing existing email IDs without notifications', {
.slice(0, 10) emailCount: transformedEmails.length,
.map(email => { unreadCount: currentUnreadCount,
const account = accountMap.get((email as any).accountId);
return {
id: email.id,
title: email.subject || 'Sans objet',
message: `De ${email.fromName || email.from.split('@')[0]}`,
link: '/courrier',
timestamp: new Date(email.date),
metadata: {
accountId: (email as any).accountId,
accountEmail: account?.email,
},
};
});
// Trigger notification update (for badge)
await triggerNotification({
source: 'email',
count: currentUnreadCount,
items: notificationItems,
}); });
lastEmailIdsRef.current = currentEmailIds;
lastUnreadCountRef.current = currentUnreadCount;
isInitializedRef.current = true;
} else {
// Trigger notification if count changed or new emails detected
if (currentUnreadCount !== lastUnreadCountRef.current || hasNewEmails) {
const previousCount = lastUnreadCountRef.current;
lastUnreadCountRef.current = currentUnreadCount;
// Dispatch event for Outlook-style notifications (only for new emails) // Prepare notification items (unread emails only, max 10)
if (previousCount >= 0 && currentUnreadCount > previousCount) { const notificationItems = transformedEmails
// Get only the newly arrived emails (the difference)
const newEmails = transformedEmails
.filter(e => !e.read) .filter(e => !e.read)
.slice(0, currentUnreadCount - previousCount); // Only the new ones .slice(0, 10)
.map(email => {
if (newEmails.length > 0) { const account = accountMap.get((email as any).accountId);
console.log('[Email Widget] 📧 Dispatching new emails event', { return {
newEmailsCount: newEmails.length, id: email.id,
previousCount, title: email.subject || 'Sans objet',
currentCount: currentUnreadCount, message: `De ${email.fromName || email.from.split('@')[0]}`,
link: '/courrier',
timestamp: new Date(email.date),
metadata: {
accountId: (email as any).accountId,
accountEmail: account?.email,
},
};
}); });
window.dispatchEvent(new CustomEvent('new-emails-detected', { // Trigger notification update (for badge)
detail: { await triggerNotification({
emails: transformedEmails, source: 'email',
accountMap: accountMap, count: currentUnreadCount,
items: notificationItems,
});
// Dispatch event for Outlook-style notifications (for new emails detected by ID)
if (hasNewEmails) {
// Get only the newly arrived emails (by ID comparison)
const newEmails = transformedEmails
.filter(e => newEmailIds.has(e.id) && !e.read)
.slice(0, 5); // Limit to 5 most recent new emails
if (newEmails.length > 0) {
console.log('[Email Widget] 📧 Dispatching new emails event', {
newEmailsCount: newEmails.length,
newEmailIds: Array.from(newEmailIds),
previousCount, previousCount,
currentCount: currentUnreadCount, currentCount: currentUnreadCount,
} previousEmailIds: Array.from(lastEmailIdsRef.current),
})); });
window.dispatchEvent(new CustomEvent('new-emails-detected', {
detail: {
emails: transformedEmails,
accountMap: accountMap,
previousCount,
currentCount: currentUnreadCount,
}
}));
}
} }
} }
} }
// Always update lastEmailIdsRef to track current state
lastEmailIdsRef.current = currentEmailIds;
// Show error only if all accounts failed // Show error only if all accounts failed
if (allEmails.length === 0 && accounts.length > 0 && Object.keys(accountErrors).length === accounts.length) { if (allEmails.length === 0 && accounts.length > 0 && Object.keys(accountErrors).length === accounts.length) {
setError('Failed to load emails from all accounts'); setError('Failed to load emails from all accounts');
@ -272,12 +297,14 @@ export function Email() {
}; };
// Integrate unified refresh for automatic polling // Integrate unified refresh for automatic polling
// Use forceRefresh=true to ensure we get the latest emails immediately
const { refresh } = useUnifiedRefresh({ const { refresh } = useUnifiedRefresh({
resource: 'email', resource: 'email',
interval: REFRESH_INTERVALS.EMAIL, // 30 seconds (harmonized) interval: REFRESH_INTERVALS.EMAIL, // 30 seconds (harmonized)
enabled: status === 'authenticated', enabled: status === 'authenticated',
onRefresh: async () => { onRefresh: async () => {
await fetchEmails(false); // Use cache for auto-refresh // Use forceRefresh to bypass cache and get latest emails immediately
await fetchEmails(true); // Force refresh to get new emails immediately
await fetchUnreadCount(); await fetchUnreadCount();
}, },
priority: 'high', priority: 'high',

View File

@ -30,62 +30,69 @@ export function useEmailNotifications() {
return; return;
} }
// Only show notifications if the count increased (new emails arrived) // Find new emails by comparing IDs (more reliable than count comparison)
// AND we have a previous count to compare with // This works even if previousCount is -1 (first load after initialization)
if (previousCount >= 0 && currentCount > previousCount) { const newEmails = emails
// Find new emails (not in lastEmailIdsRef) - these are the ones that just arrived .filter((email: any) => {
const newEmails = emails const emailId = email.id;
.filter((email: any) => { return !lastEmailIdsRef.current.has(emailId) && !email.read;
const emailId = email.id; })
return !lastEmailIdsRef.current.has(emailId) && !email.read; .slice(0, 5); // Limit to 5 most recent new emails
})
.slice(0, 5); // Limit to 5 most recent new emails
// Update lastEmailIdsRef with all current emails // Update lastEmailIdsRef with all current emails
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id)); lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id));
// If there are new unread emails, queue them for notification // If there are new unread emails, queue them for notification
if (newEmails.length > 0) { // This works regardless of previousCount value
console.log('[useEmailNotifications] 📧 New emails detected:', newEmails.length); if (newEmails.length > 0) {
console.log('[useEmailNotifications] 📧 New emails detected:', {
newEmailsCount: newEmails.length,
previousCount,
currentCount,
newEmailIds: newEmails.map((e: any) => e.id),
});
newEmails.forEach((email: any) => { newEmails.forEach((email: any) => {
const account = accountMap.get(email.accountId); const account = accountMap.get(email.accountId);
const notification: OutlookNotificationData = { const notification: OutlookNotificationData = {
id: `email-${email.id}-${Date.now()}`, id: `email-${email.id}-${Date.now()}`,
source: 'email', source: 'email',
title: 'Courrier', title: 'Courrier',
subtitle: 'Nouvel email', subtitle: 'Nouvel email',
message: `${email.subject || 'Sans objet'} - De ${email.fromName || email.from.split('@')[0]}`, message: `${email.subject || 'Sans objet'} - De ${email.fromName || email.from.split('@')[0]}`,
icon: Mail, icon: Mail,
iconColor: 'text-green-600', iconColor: 'text-green-600',
iconBgColor: 'bg-green-100', iconBgColor: 'bg-green-100',
borderColor: 'border-green-500', borderColor: 'border-green-500',
link: '/courrier', link: '/courrier',
timestamp: new Date(email.date), timestamp: new Date(email.date),
autoDismiss: 10000, // 10 seconds for emails autoDismiss: 10000, // 10 seconds for emails
actions: [ actions: [
{ {
label: 'Ouvrir', label: 'Ouvrir',
onClick: () => { onClick: () => {
window.location.href = '/courrier'; window.location.href = '/courrier';
},
variant: 'default',
className: 'bg-green-600 hover:bg-green-700 text-white',
}, },
], variant: 'default',
}; className: 'bg-green-600 hover:bg-green-700 text-white',
},
],
};
notificationQueueRef.current.push(notification); notificationQueueRef.current.push(notification);
}); });
// Show the first notification if none is currently showing // Show the first notification if none is currently showing
if (!isShowingRef.current && notificationQueueRef.current.length > 0) { if (!isShowingRef.current && notificationQueueRef.current.length > 0) {
showNextNotification(); showNextNotification();
}
} }
} else { } else {
// Just update the email IDs without showing notifications console.log('[useEmailNotifications] ⏭️ No new emails detected', {
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id)); previousCount,
currentCount,
totalEmails: emails.length,
lastEmailIdsCount: lastEmailIdsRef.current.size,
});
} }
}; };