97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { getServerSession } from 'next-auth';
|
|
import { authOptions } from "@/app/api/auth/options";
|
|
import { NotificationRegistry } from '@/lib/services/notifications/notification-registry';
|
|
import { logger } from '@/lib/logger';
|
|
|
|
// POST /api/notifications/[id]/read
|
|
export async function POST(
|
|
request: Request,
|
|
{ params }: { params: { id: string } }
|
|
) {
|
|
try {
|
|
const session = await getServerSession(authOptions);
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
|
|
}
|
|
|
|
const notificationId = params.id;
|
|
if (!notificationId) {
|
|
return NextResponse.json(
|
|
{ error: "Notification ID is required" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Parse notification ID to extract source and sourceId
|
|
// Format: "source-sourceId"
|
|
const parts = notificationId.split('-');
|
|
if (parts.length < 2) {
|
|
return NextResponse.json(
|
|
{ error: "Invalid notification ID format" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const source = parts[0];
|
|
const sourceId = parts.slice(1).join('-'); // In case sourceId contains dashes
|
|
|
|
const registry = NotificationRegistry.getInstance();
|
|
|
|
// For now, we just remove the item from the cache
|
|
// In a full implementation, you might want to store read status in a database
|
|
// For simplicity, we'll just remove it from the items cache
|
|
try {
|
|
const redis = await import('@/lib/redis').then(m => m.getRedisClient());
|
|
const itemsKey = `notifications:items:${session.user.id}:${source}`;
|
|
|
|
// Get current items
|
|
const items = await redis.get(itemsKey);
|
|
if (items) {
|
|
const parsed = JSON.parse(items);
|
|
// Filter out the read item
|
|
const filtered = parsed.filter((item: any) => item.id !== sourceId);
|
|
|
|
// Update cache
|
|
await redis.set(itemsKey, JSON.stringify(filtered), 'EX', 300);
|
|
|
|
// Update count (decrement unread)
|
|
const count = await registry.getCount(session.user.id);
|
|
if (count.sources[source] && count.sources[source].unread > 0) {
|
|
count.sources[source].unread = Math.max(0, count.sources[source].unread - 1);
|
|
count.unread = Object.values(count.sources).reduce(
|
|
(sum, s) => sum + s.unread,
|
|
0
|
|
);
|
|
|
|
const countKey = `notifications:count:${session.user.id}`;
|
|
await redis.set(countKey, JSON.stringify(count), 'EX', 30);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
logger.error('[NOTIFICATIONS_READ] Error marking as read', {
|
|
userId: session.user.id,
|
|
notificationId,
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
}
|
|
|
|
logger.debug('[NOTIFICATIONS_READ] Notification marked as read', {
|
|
userId: session.user.id,
|
|
notificationId,
|
|
source,
|
|
sourceId,
|
|
});
|
|
|
|
return NextResponse.json({ success: true });
|
|
} catch (error: any) {
|
|
logger.error('[NOTIFICATIONS_READ] Error', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
return NextResponse.json(
|
|
{ error: "Internal server error", message: error.message },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|