Notifications corrections

This commit is contained in:
alma 2026-01-16 10:16:33 +01:00
parent 28fe97edd9
commit c5295179f9

View File

@ -81,23 +81,9 @@ export function useTaskNotifications() {
notifiedCount: notifiedTaskIdsRef.current.size, notifiedCount: notifiedTaskIdsRef.current.size,
}); });
const dueTasks = tasksRef.current.filter((task) => { // Helper function to parse date correctly (handles Leantime dates with Z)
// Skip if already notified const parseTaskDate = (dateStr: string | null): Date | null => {
if (notifiedTaskIdsRef.current.has(task.id)) { if (!dateStr) return null;
console.log('[useTaskNotifications] ⏭️ Task already notified', {
id: task.id,
title: task.headline,
});
return false;
}
// For both Leantime and Twenty CRM tasks: notification at due date time (dateToFinish)
// Note: Leantime dates might be in MySQL format (YYYY-MM-DD HH:MM:SS) without timezone
// We need to parse them correctly to avoid timezone issues
let notificationDate: Date | null = null;
if (task.dateToFinish) {
const dateStr = task.dateToFinish;
// Leantime dates with 'Z' are actually local time stored as UTC // Leantime dates with 'Z' are actually local time stored as UTC
// We need to extract the time components and create a local date // We need to extract the time components and create a local date
@ -107,7 +93,7 @@ export function useTaskNotifications() {
const utcDate = new Date(dateStr); const utcDate = new Date(dateStr);
// Extract components from UTC date and create local date // Extract components from UTC date and create local date
// This assumes the UTC date actually represents local time // This assumes the UTC date actually represents local time
notificationDate = new Date( return new Date(
utcDate.getUTCFullYear(), utcDate.getUTCFullYear(),
utcDate.getUTCMonth(), utcDate.getUTCMonth(),
utcDate.getUTCDate(), utcDate.getUTCDate(),
@ -116,44 +102,45 @@ export function useTaskNotifications() {
utcDate.getUTCSeconds(), utcDate.getUTCSeconds(),
utcDate.getUTCMilliseconds() utcDate.getUTCMilliseconds()
); );
console.log('[useTaskNotifications] 📅 Parsing Leantime date (Z -> local)', {
id: task.id,
title: task.headline,
rawDate: dateStr,
utcComponents: {
year: utcDate.getUTCFullYear(),
month: utcDate.getUTCMonth(),
day: utcDate.getUTCDate(),
hour: utcDate.getUTCHours(),
minute: utcDate.getUTCMinutes(),
},
localDate: notificationDate.toLocaleString('fr-FR'),
localISO: notificationDate.toISOString(),
});
} else if (dateStr.includes('T')) { } else if (dateStr.includes('T')) {
// ISO format without Z - treat as local time // ISO format without Z - treat as local time
notificationDate = new Date(dateStr); return new Date(dateStr);
} else if (dateStr.includes(' ')) { } else if (dateStr.includes(' ')) {
// MySQL format: "YYYY-MM-DD HH:MM:SS" - parse as local time // MySQL format: "YYYY-MM-DD HH:MM:SS" - parse as local time
const isoLike = dateStr.replace(' ', 'T'); const isoLike = dateStr.replace(' ', 'T');
notificationDate = new Date(isoLike); return new Date(isoLike);
} else { } else {
// Try direct parsing // Try direct parsing
notificationDate = new Date(dateStr); return new Date(dateStr);
}
};
interface TaskWithParsedDate extends Task {
parsedNotificationDate: Date;
} }
if (!notificationDate || isNaN(notificationDate.getTime())) { const dueTasksWithDates: TaskWithParsedDate[] = [];
console.error('[useTaskNotifications] ❌ Invalid date', {
for (const task of tasksRef.current) {
// Skip if already notified
if (notifiedTaskIdsRef.current.has(task.id)) {
console.log('[useTaskNotifications] ⏭️ Task already notified', {
id: task.id, id: task.id,
rawDate: dateStr, title: task.headline,
}); });
return false; continue;
}
} }
// Parse the notification date
const notificationDate = parseTaskDate(task.dateToFinish);
if (!notificationDate || isNaN(notificationDate.getTime())) { if (!notificationDate || isNaN(notificationDate.getTime())) {
return false; console.log('[useTaskNotifications] ⏭️ Task has no valid date', {
id: task.id,
title: task.headline,
dateToFinish: task.dateToFinish,
});
continue;
} }
const notificationTime = notificationDate.getTime(); const notificationTime = notificationDate.getTime();
@ -182,23 +169,25 @@ export function useTaskNotifications() {
inWindow: inNotificationWindow, inWindow: inNotificationWindow,
}); });
return inNotificationWindow; if (inNotificationWindow) {
dueTasksWithDates.push({
...task,
parsedNotificationDate: notificationDate,
}); });
}
}
const dueTasks = dueTasksWithDates;
if (dueTasks.length > 0) { if (dueTasks.length > 0) {
// Sort by notification time (earliest first) // Sort by notification time (earliest first) using parsed dates
dueTasks.sort((a, b) => { dueTasks.sort((a, b) => {
const dateA = a.dateToFinish ? new Date(a.dateToFinish).getTime() : Infinity; return a.parsedNotificationDate.getTime() - b.parsedNotificationDate.getTime();
const dateB = b.dateToFinish ? new Date(b.dateToFinish).getTime() : Infinity;
return dateA - dateB;
}); });
// Show notification for the first task // Show notification for the first task
const task = dueTasks[0]; const task = dueTasks[0];
const notificationDate = task.parsedNotificationDate;
const notificationDate = task.dateToFinish
? new Date(task.dateToFinish)
: new Date();
const timeStr = format(notificationDate, 'HH:mm', { locale: fr }); const timeStr = format(notificationDate, 'HH:mm', { locale: fr });
const sourceLabel = task.source === 'twenty-crm' ? 'Médiation' : 'Agilité'; const sourceLabel = task.source === 'twenty-crm' ? 'Médiation' : 'Agilité';
@ -207,8 +196,11 @@ export function useTaskNotifications() {
id: task.id, id: task.id,
title: task.headline, title: task.headline,
source: task.source, source: task.source,
notificationDate: notificationDate.toISOString(), rawDate: task.dateToFinish,
now: now.toISOString(), parsedNotificationDateLocal: notificationDate.toLocaleString('fr-FR'),
parsedNotificationDateISO: notificationDate.toISOString(),
nowLocal: now.toLocaleString('fr-FR'),
nowISO: now.toISOString(),
}); });
const notification: OutlookNotificationData = { const notification: OutlookNotificationData = {