feat: link tickets in comments and align admin sidebars
This commit is contained in:
parent
c35eb673d3
commit
b0f57009ac
15 changed files with 1606 additions and 424 deletions
96
src/app/api/tickets/mentions/route.ts
Normal file
96
src/app/api/tickets/mentions/route.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import { NextResponse } from "next/server"
|
||||
|
||||
import { assertAuthenticatedSession } from "@/lib/auth-server"
|
||||
import { DEFAULT_TENANT_ID } from "@/lib/constants"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
|
||||
export const runtime = "nodejs"
|
||||
|
||||
const MAX_RESULTS = 10
|
||||
const MAX_SCAN = 60
|
||||
|
||||
function normalizeRole(role?: string | null) {
|
||||
return (role ?? "").toLowerCase()
|
||||
}
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const session = await assertAuthenticatedSession()
|
||||
if (!session) {
|
||||
return NextResponse.json({ items: [] }, { status: 401 })
|
||||
}
|
||||
|
||||
const normalizedRole = normalizeRole(session.user.role)
|
||||
const isAgentOrAdmin = normalizedRole === "admin" || normalizedRole === "agent"
|
||||
const canLinkOwnTickets = normalizedRole === "collaborator"
|
||||
|
||||
if (!isAgentOrAdmin && !canLinkOwnTickets) {
|
||||
return NextResponse.json({ items: [] }, { status: 403 })
|
||||
}
|
||||
|
||||
const tenantId = session.user.tenantId ?? DEFAULT_TENANT_ID
|
||||
const url = new URL(request.url)
|
||||
const rawQuery = url.searchParams.get("q") ?? ""
|
||||
const query = rawQuery.trim()
|
||||
|
||||
const whereBase: {
|
||||
tenantId: string
|
||||
requesterId?: string
|
||||
} = { tenantId }
|
||||
|
||||
if (!isAgentOrAdmin) {
|
||||
whereBase.requesterId = session.user.id
|
||||
}
|
||||
|
||||
const numericQuery = /^\d+$/.test(query)
|
||||
|
||||
const take = numericQuery ? MAX_RESULTS : MAX_SCAN
|
||||
|
||||
const tickets = await prisma.ticket.findMany({
|
||||
where: whereBase,
|
||||
include: {
|
||||
assignee: { select: { name: true } },
|
||||
requester: { select: { name: true } },
|
||||
company: { select: { name: true } },
|
||||
},
|
||||
orderBy: { updatedAt: "desc" },
|
||||
take,
|
||||
})
|
||||
|
||||
const lowered = query.toLowerCase()
|
||||
|
||||
const filtered = tickets
|
||||
.filter((ticket) => {
|
||||
if (!query) return true
|
||||
const referenceMatch = String(ticket.reference).includes(query)
|
||||
if (referenceMatch) return true
|
||||
const subject = ticket.subject ?? ""
|
||||
if (subject.toLowerCase().includes(lowered)) return true
|
||||
const requesterName = ticket.requester?.name ?? ""
|
||||
if (requesterName.toLowerCase().includes(lowered)) return true
|
||||
const companyName = ticket.company?.name ?? ""
|
||||
if (companyName.toLowerCase().includes(lowered)) return true
|
||||
return false
|
||||
})
|
||||
.slice(0, MAX_RESULTS)
|
||||
|
||||
const basePath = isAgentOrAdmin ? "/tickets" : "/portal/tickets"
|
||||
|
||||
const items = filtered.map((ticket) => {
|
||||
const subject = ticket.subject ?? ""
|
||||
return {
|
||||
id: ticket.id,
|
||||
reference: ticket.reference,
|
||||
subject,
|
||||
status: ticket.status,
|
||||
priority: ticket.priority,
|
||||
requesterName: ticket.requester?.name ?? null,
|
||||
assigneeName: ticket.assignee?.name ?? null,
|
||||
companyName: ticket.company?.name ?? null,
|
||||
url: `${basePath}/${ticket.id}`,
|
||||
updatedAt: ticket.updatedAt.toISOString(),
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ items })
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue