Fix admin cleanup hook order and lint setup
This commit is contained in:
parent
37c32149a6
commit
c7aaa60d9a
4 changed files with 1886 additions and 31 deletions
|
|
@ -61,9 +61,9 @@
|
|||
"pdfkit": "^0.17.2",
|
||||
"postcss": "^8.5.6",
|
||||
"react": "19.2.0",
|
||||
"react-aria-components": "^1.4.0",
|
||||
"react-dom": "19.2.0",
|
||||
"react-hook-form": "^7.64.0",
|
||||
"react-aria-components": "^1.4.0",
|
||||
"recharts": "^2.15.4",
|
||||
"sanitize-html": "^2.17.0",
|
||||
"sonner": "^2.0.7",
|
||||
|
|
@ -98,6 +98,7 @@
|
|||
"tsconfig-paths": "^4.2.0",
|
||||
"tw-animate-css": "^1.3.8",
|
||||
"typescript": "^5",
|
||||
"typescript-eslint": "^8.46.2",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^4.0.1"
|
||||
}
|
||||
|
|
|
|||
1841
pnpm-lock.yaml
generated
1841
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,28 @@ export const runtime = "nodejs"
|
|||
|
||||
const MAX_RESULTS = 10
|
||||
|
||||
type TicketRecord = {
|
||||
id: string | number
|
||||
reference: string | number
|
||||
subject?: string | null
|
||||
status?: string | null
|
||||
priority?: string | null
|
||||
requester?: { name?: string | null } | null
|
||||
assignee?: { name?: string | null } | null
|
||||
company?: { name?: string | null } | null
|
||||
updatedAt?: number | null
|
||||
}
|
||||
|
||||
function isTicketRecord(value: unknown): value is TicketRecord {
|
||||
if (!value || typeof value !== "object") {
|
||||
return false
|
||||
}
|
||||
const record = value as Record<string, unknown>
|
||||
const hasValidId = typeof record.id === "string" || typeof record.id === "number"
|
||||
const hasValidReference = typeof record.reference === "string" || typeof record.reference === "number"
|
||||
return hasValidId && hasValidReference
|
||||
}
|
||||
|
||||
function normalizeRole(role?: string | null) {
|
||||
return (role ?? "").toLowerCase()
|
||||
}
|
||||
|
|
@ -59,25 +81,15 @@ export async function GET(request: Request) {
|
|||
}
|
||||
|
||||
// Pesquisar pelos tickets visíveis ao viewer (assunto, resumo ou #referência)
|
||||
let tickets: Array<{
|
||||
id: string
|
||||
reference: number
|
||||
subject: string
|
||||
status: string
|
||||
priority: string
|
||||
requester?: { name?: string | null } | null
|
||||
assignee?: { name?: string | null } | null
|
||||
company?: { name?: string | null } | null
|
||||
updatedAt?: number | null
|
||||
}> = []
|
||||
let tickets: TicketRecord[] = []
|
||||
try {
|
||||
const res = (await client.query(api.tickets.list, {
|
||||
const res = await client.query(api.tickets.list, {
|
||||
tenantId,
|
||||
viewerId: viewerId as unknown as Id<"users">,
|
||||
search: query,
|
||||
limit: 40,
|
||||
})) as any[]
|
||||
tickets = Array.isArray(res) ? res : []
|
||||
})
|
||||
tickets = Array.isArray(res) ? res.filter(isTicketRecord) : []
|
||||
} catch (error) {
|
||||
console.error("[mentions] tickets.list failed", error)
|
||||
return NextResponse.json({ items: [] }, { status: 500 })
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Link from "next/link"
|
||||
import { useCallback, useEffect, useMemo, useState, useTransition } from "react"
|
||||
import { IconSearch, IconUserPlus, IconTrash } from "@tabler/icons-react"
|
||||
import { IconSearch, IconUserPlus, IconTrash, IconAlertTriangle } from "@tabler/icons-react"
|
||||
|
||||
import { toast } from "sonner"
|
||||
|
||||
|
|
@ -273,21 +273,6 @@ export function AdminUsersManager({
|
|||
return Array.from(unique)
|
||||
}, [normalizedRoles, viewerIsAdmin])
|
||||
|
||||
const buildKeepEmailSet = useCallback(() => {
|
||||
const keep = new Set<string>()
|
||||
DEFAULT_KEEP_EMAILS.forEach((email) => keep.add(email.toLowerCase()))
|
||||
if (viewerEmail) {
|
||||
keep.add(viewerEmail)
|
||||
}
|
||||
cleanupKeepEmails
|
||||
.split(",")
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean)
|
||||
.forEach((email) => keep.add(email))
|
||||
return keep
|
||||
}, [cleanupKeepEmails, viewerEmail])
|
||||
|
||||
const cleanupPreview = useMemo(() => Array.from(buildKeepEmailSet()).join(", "), [buildKeepEmailSet])
|
||||
// Split users: team (admin/agent) and people (manager/collaborator); exclude machines
|
||||
const teamUsers = useMemo(
|
||||
() => users.filter((user) => user.role !== "machine" && ["admin", "agent"].includes(coerceRole(user.role))),
|
||||
|
|
@ -331,6 +316,22 @@ export function AdminUsersManager({
|
|||
const [cleanupKeepEmails, setCleanupKeepEmails] = useState(DEFAULT_KEEP_EMAILS.join(", "))
|
||||
const [cleanupPending, setCleanupPending] = useState(false)
|
||||
|
||||
const buildKeepEmailSet = useCallback(() => {
|
||||
const keep = new Set<string>()
|
||||
DEFAULT_KEEP_EMAILS.forEach((email) => keep.add(email.toLowerCase()))
|
||||
if (viewerEmail) {
|
||||
keep.add(viewerEmail)
|
||||
}
|
||||
cleanupKeepEmails
|
||||
.split(",")
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean)
|
||||
.forEach((email) => keep.add(email))
|
||||
return keep
|
||||
}, [cleanupKeepEmails, viewerEmail])
|
||||
|
||||
const cleanupPreview = useMemo(() => Array.from(buildKeepEmailSet()).join(", "), [buildKeepEmailSet])
|
||||
|
||||
// Máquinas (para listar vínculos por usuário)
|
||||
type MachinesListItem = {
|
||||
id: string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue