1
0
Fork 0
polaris-task-force/src/app/(frontend)/notifications/actions.ts
Z8MB1E 9c15117b9b feat(notifications): add in-app player notification center
- user-notifications collection (per-user inbox, owner-scoped read)
- notifyUser() fire-and-forget helper + notification label mapping
- NotificationsBell in the site header with 30s polling, unread badge,
  mark-read on click, and "Mark all read"
- markNotificationsRead / markAllNotificationsRead server actions
2026-08-10 16:02:55 -04:00

81 lines
2.3 KiB
TypeScript

"use server";
import config from "@payload-config";
import { getPayload } from "payload";
export interface NotificationActionResult {
success: boolean;
error?: string;
}
export async function markNotificationsRead(ids: number[]): Promise<NotificationActionResult> {
try {
const payloadConfig = await config;
const payload = await getPayload({ config: payloadConfig });
const { headers } = await import("next/headers");
const hdrs = await headers();
const { user } = await payload.auth({ headers: hdrs, canSetHeaders: false });
if (!user) return { success: false, error: "You must be logged in." };
const cleanIds = [...new Set(ids.filter((id) => Number.isFinite(id) && id > 0))];
if (cleanIds.length === 0) return { success: true };
// Query with access control so users can only touch their own notifications.
const found = await payload.find({
collection: "user-notifications",
where: { id: { in: cleanIds } },
limit: Math.min(cleanIds.length, 100),
depth: 0,
});
for (const doc of found.docs) {
if (!doc.read) {
await payload.update({
collection: "user-notifications",
id: doc.id,
data: { read: true },
overrideAccess: true,
depth: 0,
});
}
}
return { success: true };
} catch {
return { success: false, error: "Failed to update notifications." };
}
}
export async function markAllNotificationsRead(): Promise<NotificationActionResult> {
try {
const payloadConfig = await config;
const payload = await getPayload({ config: payloadConfig });
const { headers } = await import("next/headers");
const hdrs = await headers();
const { user } = await payload.auth({ headers: hdrs, canSetHeaders: false });
if (!user) return { success: false, error: "You must be logged in." };
const unread = await payload.find({
collection: "user-notifications",
where: { read: { equals: false } },
limit: 100,
depth: 0,
});
for (const doc of unread.docs) {
await payload.update({
collection: "user-notifications",
id: doc.id,
data: { read: true },
overrideAccess: true,
depth: 0,
});
}
return { success: true };
} catch {
return { success: false, error: "Failed to update notifications." };
}
}