Functions update

This commit is contained in:
Milan Paunovic
2025-02-06 09:44:06 +01:00
parent 5ac4526baf
commit 300ce82a4d
2 changed files with 71 additions and 46 deletions

View File

@ -17,8 +17,21 @@ export const useCalendarControls = (events: any[]) => {
const handlePressEvent = useCallback((event: any) => {
const foundEvent = events?.find(x => x.id === event.id);
setEditVisible(true);
setEventForEdit(foundEvent!);
if (foundEvent) {
const processedEvent = {
...foundEvent,
startDate: foundEvent.startDate?.seconds ?
new Date(foundEvent.startDate.seconds * 1000) :
new Date(foundEvent.start),
endDate: foundEvent.endDate?.seconds ?
new Date(foundEvent.endDate.seconds * 1000) :
new Date(foundEvent.end)
};
setEditVisible(true);
setEventForEdit(processedEvent);
}
}, [events, setEditVisible, setEventForEdit]);
const handlePressCell = useCallback((date: DateOrDateTime) => {

View File

@ -313,18 +313,22 @@ exports.checkUpcomingEvents = functions.pubsub
.schedule("every 5 minutes")
.onRun(async (context) => {
const now = Timestamp.now();
const tenMinutesFromNow = new Date(now.toDate().getTime() + 10 * 60 * 1000);
const eventsSnapshot = await db.collection("Events")
.where("startDate", ">=", now)
.where("startDate", "<=", Timestamp.fromDate(tenMinutesFromNow))
.get();
await Promise.all(eventsSnapshot.docs.map(async (doc) => {
const event = doc.data();
if (!event?.startDate) return;
const { familyId, title, allDay } = event;
try {
const familyDoc = await db.collection("Families").doc(familyId).get();
const familyDoc = await db.collection("Households").doc(familyId).get();
if (!familyDoc.exists) return;
const familySettings = familyDoc.data()?.settings || {};
const reminderTime = familySettings.defaultReminderTime || 15;
const reminderTime = familySettings.defaultReminderTime || 5;
const eventTime = event.startDate.toDate();
const reminderThreshold = new Date(now.toDate().getTime() + reminderTime * 60 * 1000);
if (allDay) {
@ -460,6 +464,13 @@ exports.syncNewEventToGoogle = functions.firestore
.onCreate(async (snapshot, context) => {
const newEvent = snapshot.data();
const eventId = context.params.eventId;
await snapshot.ref.update({
reminderSent: false,
eveningReminderSent: false,
notifiedAt: null
});
if (newEvent.externalOrigin === "google") {
logger.info("[GOOGLE_SYNC] Skipping sync for Google-originated event", eventId);
return;
@ -1132,19 +1143,19 @@ exports.notifyOnEventUpdate = functions.firestore
───────────────────────────────── */
// We keep the reminder scheduler mostly as-is but ensure that once a notification is sent, the event is updated
exports.checkUpcomingEvents = functions.pubsub
.schedule("every 5 minutes") // Run more frequently to catch reminders
.schedule("every 5 minutes")
.onRun(async (context) => {
const now = Timestamp.now();
const thirtyMinutesFromNow = new Date(now.toDate().getTime() + 30 * 60 * 1000);
// Query only events starting in the next 30 minutes that haven't been reminded
logger.info(`Running check at ${now.toDate().toISOString()}`);
const eventsSnapshot = await db.collection("Events")
.where("startDate", ">=", now)
.where("startDate", "<=", thirtyMinutesFromNow)
.where("reminderSent", "==", false) // Only get events that haven't been reminded
.where("startDate", "<=", Timestamp.fromDate(thirtyMinutesFromNow))
.get();
const batch = db.batch(); // Batch our updates
const batch = db.batch();
const notificationPromises = [];
for (const doc of eventsSnapshot.docs) {
@ -1152,64 +1163,65 @@ exports.checkUpcomingEvents = functions.pubsub
if (!event?.startDate) continue;
const { familyId, title, allDay } = event;
// Skip if reminder already sent
if (event.reminderSent) {
logger.info(`Reminder already sent for event: ${title}`);
continue;
}
try {
const familyDoc = await db.collection("Families").doc(familyId).get();
if (!familyDoc.exists) continue;
const familySettings = familyDoc.data()?.settings || {};
const reminderTime = familySettings.defaultReminderTime || 10; // Default to 10 minutes
const eventTime = event.startDate.toDate();
const reminderThreshold = new Date(now.toDate().getTime() + reminderTime * 60 * 1000);
const reminderTime = familySettings.defaultReminderTime || 10;
// Check if we're within the reminder window
const eventTime = event.startDate.toDate();
const timeUntilEvent = eventTime.getTime() - now.toDate().getTime();
const minutesUntilEvent = Math.floor(timeUntilEvent / (60 * 1000));
logger.info(`Checking event: "${title}"`, {
minutesUntilEvent,
reminderTime,
eventTime: eventTime.toISOString()
});
// Modified timing logic: Send reminder when we're close to the reminder time
// This ensures we don't miss the window between function executions
if (minutesUntilEvent <= reminderTime && minutesUntilEvent > 0) {
notificationPromises.push(async () => {
const pushTokens = await getPushTokensForFamily(familyId);
if (pushTokens.length) {
await sendNotifications(pushTokens, {
title: "Upcoming Event",
body: `In ${minutesUntilEvent} minutes: ${title}`,
data: { type: 'event_reminder', eventId: doc.id }
});
batch.update(doc.ref, { reminderSent: true });
}
});
}
logger.info(`Preparing to send reminder for: ${title}`);
const pushTokens = await getPushTokensForFamily(familyId);
// Handle all-day events separately
if (allDay && !event.eveningReminderSent) {
const eveningBefore = new Date(eventTime);
eveningBefore.setDate(eveningBefore.getDate() - 1);
eveningBefore.setHours(20, 0, 0, 0);
if (now.toDate() >= eveningBefore) {
notificationPromises.push(async () => {
const pushTokens = await getPushTokensForFamily(familyId);
if (pushTokens.length) {
await sendNotifications(pushTokens, {
title: "Tomorrow's All-Day Event",
body: `Tomorrow: ${title}`,
data: { type: 'event_reminder', eventId: doc.id }
});
batch.update(doc.ref, { eveningReminderSent: true });
}
if (pushTokens.length) {
await sendNotifications(pushTokens, {
title: "Upcoming Event",
body: `In ${minutesUntilEvent} minutes: ${title}`,
data: { type: 'event_reminder', eventId: doc.id }
});
batch.update(doc.ref, {
reminderSent: true,
lastReminderSent: Timestamp.now()
});
logger.info(`Reminder sent for: ${title}`);
}
} else {
logger.info(`Not yet time for reminder: ${title}`, {
minutesUntilEvent,
reminderTime
});
}
} catch (error) {
logger.error(`Error processing reminder for event ${doc.id}:`, error);
}
}
// Execute all notifications
await Promise.all(notificationPromises.map(fn => fn()));
// Commit all updates in one batch
// Commit batch if there are any operations
if (batch._ops.length > 0) {
await batch.commit();
logger.info(`Committed ${batch._ops.length} updates`);
}
});