Files
CRM_ENVR/src/app/api/notifications/route.ts
T
Ace d35c806d5b feat: Enhance provider components with detailed documentation and comments
- Added comprehensive comments and JSDoc-style documentation to NotificationProvider, ThemeProvider, UserProvider, and WebsiteThemeProvider for better clarity and maintainability.
- Improved type definitions in index.ts for better code understanding and usage.
- Introduced Docker support with Dockerfiles for various services including AI server, signaling server, and browser-use service.
- Created a docker-compose.yml file to orchestrate multiple services including PostgreSQL, AI, scraper, and frontend.
- Added a startup guide (startup.txt) for setting up the CRM environment on Ubuntu with Docker.
- Included a .dockerignore file to exclude unnecessary files from Docker builds.
2026-07-13 13:05:30 +02:00

110 lines
4.2 KiB
TypeScript

// ── Notifications: Collection ────────────────────────────────────────────────
// GET /api/notifications — List the current user's recent notifications
// POST /api/notifications — Create a new notification (self or target user)
// PATCH /api/notifications — Mark all unread notifications as read
//
// Auth: authenticated
import { NextRequest, NextResponse } from "next/server"
import { getSessionUser } from "@/lib/auth"
import { query } from "@/lib/db"
// ── GET ──────────────────────────────────────────────────────────────────────
export async function GET() {
try {
const user = await getSessionUser()
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
const result = await query(
`SELECT id, type, title, description, link, is_read, created_at, context_id, context_type
FROM notifications
WHERE user_id = $1
ORDER BY created_at DESC
LIMIT 50`,
[user.id],
)
const notifications = result.rows.map((r: any) => ({
id: r.id,
type: r.type,
title: r.title,
description: r.description,
link: r.link,
read: r.is_read,
timestamp: r.created_at,
contextId: r.context_id,
contextType: r.context_type,
}))
// Also return total unread count for badge display
const unreadResult = await query(
`SELECT COUNT(*) AS count FROM notifications WHERE user_id = $1 AND is_read = FALSE`,
[user.id],
)
return NextResponse.json({
notifications,
unreadCount: parseInt(unreadResult.rows[0].count, 10),
})
} catch (error) {
console.error("Notifications GET error:", error)
return NextResponse.json({ error: "Failed to load notifications" }, { status: 500 })
}
}
// ── POST ─────────────────────────────────────────────────────────────────────
export async function POST(request: NextRequest) {
try {
const user = await getSessionUser()
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
const { type, title, description, link, userId } = await request.json()
const isAdmin = user.role === "admin" || user.role === "super_admin"
// Only admins can create notifications for other users; otherwise self-only
const targetUserId = (userId && isAdmin) ? userId : user.id
const result = await query(
`INSERT INTO notifications (user_id, type, title, description, link)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, type, title, description, link, is_read, created_at`,
[targetUserId, type, title, description || null, link || null],
)
const notif = result.rows[0]
return NextResponse.json({
id: notif.id,
type: notif.type,
title: notif.title,
description: notif.description,
link: notif.link,
read: notif.is_read,
timestamp: notif.created_at,
}, { status: 201 })
} catch (error) {
console.error("Notifications POST error:", error)
return NextResponse.json({ error: "Failed to create notification" }, { status: 500 })
}
}
// ── PATCH ────────────────────────────────────────────────────────────────────
export async function PATCH() {
try {
const user = await getSessionUser()
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
// Mark all unread notifications as read for the current user
await query(
`UPDATE notifications SET is_read = TRUE WHERE user_id = $1 AND is_read = FALSE`,
[user.id],
)
return NextResponse.json({ success: true })
} catch (error) {
console.error("Notifications PATCH error:", error)
return NextResponse.json({ error: "Failed to mark all as read" }, { status: 500 })
}
}