feat: add sendMentionEmail func
This commit is contained in:
131
packages/api/src/utils/notifications.ts
Normal file
131
packages/api/src/utils/notifications.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { env } from "next-runtime-env";
|
||||
|
||||
import type { dbClient } from "@kan/db/client";
|
||||
import * as cardRepo from "@kan/db/repository/card.repo";
|
||||
import * as memberRepo from "@kan/db/repository/member.repo";
|
||||
import * as notificationRepo from "@kan/db/repository/notification.repo";
|
||||
import * as userRepo from "@kan/db/repository/user.repo";
|
||||
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
|
||||
import { sendEmail } from "@kan/email";
|
||||
import { parseMentionsFromHTML } from "@kan/shared/utils";
|
||||
|
||||
/**
|
||||
* Sends mention notification emails to mentioned members
|
||||
* Only sends emails for new mentions (checks notification table to avoid duplicates)
|
||||
*/
|
||||
export async function sendMentionEmails({
|
||||
db,
|
||||
cardPublicId,
|
||||
commentHtml,
|
||||
commenterUserId,
|
||||
commentId,
|
||||
}: {
|
||||
db: dbClient;
|
||||
cardPublicId: string;
|
||||
commentHtml: string;
|
||||
commenterUserId: string;
|
||||
commentId?: number;
|
||||
}) {
|
||||
try {
|
||||
// Parse mentions from HTML
|
||||
const mentionPublicIds = parseMentionsFromHTML(commentHtml);
|
||||
if (mentionPublicIds.length === 0) return;
|
||||
|
||||
// Get card with board information
|
||||
const card = await cardRepo.getWithListAndMembersByPublicId(db, cardPublicId);
|
||||
if (!card?.list.board) return;
|
||||
|
||||
const board = card.list.board;
|
||||
const boardName = board.name;
|
||||
const cardTitle = card.title;
|
||||
const cardId = card.id;
|
||||
|
||||
// Get workspace ID from workspace publicId
|
||||
const workspace = await workspaceRepo.getByPublicId(
|
||||
db,
|
||||
board.workspace.publicId,
|
||||
);
|
||||
if (!workspace?.id) return;
|
||||
|
||||
const workspaceId = workspace.id;
|
||||
|
||||
// Get commenter information
|
||||
const commenter = await userRepo.getById(db, commenterUserId);
|
||||
if (!commenter) return;
|
||||
|
||||
const commenterName = commenter.name ?? commenter.email;
|
||||
|
||||
// Get mentioned members with full details (filtered by workspace)
|
||||
const membersWithDetails = await memberRepo.getByPublicIdsWithUsers(
|
||||
db,
|
||||
mentionPublicIds,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
// Filter out the commenter
|
||||
const membersToNotify = membersWithDetails.filter(
|
||||
(member) => member.user?.id !== commenterUserId,
|
||||
);
|
||||
|
||||
if (membersToNotify.length === 0) return;
|
||||
|
||||
const baseUrl = env("NEXT_PUBLIC_BASE_URL");
|
||||
const cardUrl = `${baseUrl}/cards/${cardPublicId}`;
|
||||
|
||||
// Send emails to all mentioned members (only if notification doesn't exist)
|
||||
await Promise.all(
|
||||
membersToNotify.map(async (member) => {
|
||||
const userId = member.user?.id;
|
||||
const email = member.user?.email ?? member.email;
|
||||
if (!userId || !email) return;
|
||||
|
||||
try {
|
||||
// Check if notification already exists for this mention
|
||||
const notificationExists = await notificationRepo.exists(db, {
|
||||
userId,
|
||||
cardId,
|
||||
type: "mention",
|
||||
});
|
||||
|
||||
// If notification already exists, skip sending email
|
||||
if (notificationExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create notification record
|
||||
await notificationRepo.create(db, {
|
||||
type: "mention",
|
||||
userId,
|
||||
cardId,
|
||||
commentId,
|
||||
});
|
||||
|
||||
// Send email
|
||||
await sendEmail(
|
||||
email,
|
||||
`${commenterName} mentioned you in a comment on ${cardTitle}`,
|
||||
"MENTION",
|
||||
{
|
||||
commenterName,
|
||||
boardName,
|
||||
cardTitle,
|
||||
cardUrl,
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to send mention email:", {
|
||||
email,
|
||||
cardPublicId,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error sending mention emails:", {
|
||||
cardPublicId,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user