Closer/functions/src/dates/onDateHistoryCreated.ts

62 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { recipientInQuietHours } from '../notifications/quietHours'
/**
* Fires when a date is logged as completed (`couples/{coupleId}/date_history/{dateId}` created). Nudges
* the OTHER partner (not the one who logged it) to add their reflection — so the reflect→reveal loop
* starts even if the logger doesn't reflect right away. Gated on `notifPartnerAnswered` + quiet hours.
*/
export const onDateHistoryCreated = functions.firestore
.document('couples/{coupleId}/date_history/{dateId}')
.onCreate(async (snap, context) => {
const { coupleId, dateId } = context.params as { coupleId: string; dateId: string }
const db = admin.firestore()
const addedBy = snap.data()?.addedBy as string | undefined
const coupleDoc = await db.collection('couples').doc(coupleId).get()
if (!coupleDoc.exists) return
const userIds = (coupleDoc.data()?.userIds ?? []) as string[]
const partnerId = userIds.find((u) => u !== addedBy)
if (!partnerId) return
const partnerUserDoc = await db.collection('users').doc(partnerId).get()
if (partnerUserDoc.data()?.notifPartnerAnswered === false) return
const title = 'You went on a date 💜'
const body = 'Reflect on it together while its fresh.'
await db.collection('users').doc(partnerId).collection('notification_queue').add({
type: 'date_logged', title, body, read: false, createdAt: admin.firestore.FieldValue.serverTimestamp(),
})
if (recipientInQuietHours(partnerUserDoc.data())) return
const tokens: string[] = []
const legacy = partnerUserDoc.data()?.fcmToken
if (typeof legacy === 'string' && legacy.length > 0) tokens.push(legacy)
const tokenSnap = await db.collection('users').doc(partnerId).collection('fcmTokens').get()
tokenSnap.docs.forEach((d) => {
const t = d.data()?.token
if (typeof t === 'string' && t.length > 0 && !tokens.includes(t)) tokens.push(t)
})
if (tokens.length === 0) return
const payload: admin.messaging.MessagingPayload = {
notification: { title, body },
data: { type: 'date_logged', couple_id: coupleId, date_id: dateId },
}
const results = await Promise.allSettled(
tokens.map((token) =>
admin.messaging().send({
...payload,
token,
android: { notification: { channelId: 'partner_activity' } },
} as admin.messaging.Message)
)
)
results.forEach((r, i) => {
if (r.status === 'rejected') console.warn(`[onDateHistoryCreated] FCM failed for ${tokens[i]}:`, r.reason)
})
})